KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > deployment > DeploymentInfo


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.deployment;
23
24 import java.io.File JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.Serializable JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.net.URLClassLoader JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Collection JavaDoc;
31 import java.util.Date JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.jar.JarFile JavaDoc;
37 import java.util.jar.Manifest JavaDoc;
38
39 import javax.management.MBeanServer JavaDoc;
40 import javax.management.ObjectName JavaDoc;
41
42 import org.jboss.logging.Logger;
43 import org.jboss.mx.loading.LoaderRepositoryFactory;
44 import org.jboss.mx.loading.RepositoryClassLoader;
45 import org.jboss.mx.loading.LoaderRepositoryFactory.LoaderRepositoryConfig;
46 import org.jboss.util.collection.ListSet;
47 import org.jboss.util.file.Files;
48 import org.w3c.dom.Document JavaDoc;
49
50 /**
51  * Service Deployment Info .
52  *
53  * Every deployment (even the J2EE ones) should be seen at some point as
54  * Service Deployment info
55  *
56  * @see org.jboss.system.Service
57  *
58  * @author <a HREF="mailto:marc.fleury@jboss.org">Marc Fleury</a>
59  * @author <a HREF="mailto:David.Maplesden@orion.co.nz">David Maplesden</a>
60  * @author <a HREF="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
61  * @author <a HREF="mailto:daniel.schulze@telkel.com">Daniel Schulze</a>
62  * @author <a HREF="mailto:Christoph.Jung@infor.de">Christoph G. Jung</a>
63  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark</a>
64  * @version $Revision: 57108 $ <p>
65  */

66 public class DeploymentInfo implements Serializable JavaDoc
67 {
68    /** @since 4.0.1 */
69    private static final long serialVersionUID = 1131841473723490707L;
70    
71    private static final Logger log = Logger.getLogger(DeploymentInfo.class);
72
73    // Variables ------------------------------------------------------------
74

75    /** The initial construction timestamp */
76    public Date JavaDoc date = new Date JavaDoc();
77
78    /** the URL identifing this SDI **/
79    public URL JavaDoc url;
80    
81    /** An optional URL to a local copy of the deployment */
82    public URL JavaDoc localUrl;
83    
84    /** The URL used to watch for changes when the deployment is unpacked */
85    public URL JavaDoc watch;
86    
87    /** The suffix of the deployment url */
88    public String JavaDoc shortName;
89    
90    /** The last system time the deployment inited by the MainDeployer */
91    public long lastDeployed = 0;
92    
93    /** use for "should we redeploy failed" */
94    public long lastModified = 0;
95
96    /** A free form status for the "state" can be Deployed/failed etc etc */
97    public String JavaDoc status;
98    
99    /** The current state of the deployment */
100    public DeploymentState state = DeploymentState.CONSTRUCTED;
101    
102    /** The subdeployer that handles the deployment */
103    public transient SubDeployer deployer;
104
105    /** Unified CL is a global scope class loader **/
106    public transient RepositoryClassLoader ucl;
107
108    /** local Cl is a CL that is used for metadata loading, if ejb-jar.xml is
109     left in the parent CL through old deployments, this makes sure that we
110     use the local version. You must use the URLClassLoader.findResource method
111     to restrict loading to the deployment URL.
112     */

113    public transient URLClassLoader JavaDoc localCl;
114    
115    /** A CL for preloading annotations, it should be made available
116     * in the deployment create step.
117     */

118    public transient URLClassLoader JavaDoc annotationsCl;
119
120    /** The classpath declared by this xml descriptor, needs <classpath> entry **/
121    public final Collection JavaDoc classpath = new ArrayList JavaDoc();
122
123    /** The mbeans deployed */
124    public final List JavaDoc<ObjectName JavaDoc> mbeans = new ArrayList JavaDoc<ObjectName JavaDoc>();
125
126    /** Anyone can have subdeployments */
127    public final Set JavaDoc subDeployments = new ListSet();
128
129    /** And the subDeployments have a parent */
130    public DeploymentInfo parent = null;
131
132    /** the web root context in case of war file */
133    public String JavaDoc webContext;
134
135    /** the manifest entry of the deployment (if any)
136    * manifest is not serializable ... is only needed
137    * at deployment time, so we mark it transient
138    */

139    public transient Manifest JavaDoc manifest;
140
141    /**
142     * Each Deployment is really mapping one to one to a XML document, here in
143     * its parsed form. A xerces document (org.apache.xerces.dom.DocumentImpl)
144     * is serializable.
145     */

146    public Document JavaDoc document;
147
148    /** An optional URL to the URL of the document loaded */
149    public URL JavaDoc documentUrl;
150
151    /** We can hold "typed" metadata, really an interpretation of the bare XML document */
152    public transient Object JavaDoc metaData;
153    
154    /** If this deployed as part of an EAR, there may be an alernative DD */
155    public String JavaDoc alternativeDD;
156    
157    /** An arbitrary map of state associated with the deployment */
158    public transient HashMap JavaDoc context = new HashMap JavaDoc();
159    
160    /** Is this a stand-alone service descriptor */
161    public boolean isXML;
162    
163    /** Is this a stand-alone script */
164    public boolean isScript;
165    
166    /** Does the deployment url point to a directory */
167    public boolean isDirectory;
168
169    /** Are the subdeploymets already sorted */
170    public boolean sortedSubDeployments = false ;
171    /**
172     * The variable <code>deployedObject</code> can contain the MBean that
173     * is created through the deployment. for instance, deploying an ejb-jar
174     * results in an EjbModule mbean, which is stored here.
175     */

176    public ObjectName JavaDoc deployedObject;
177    
178    /** The configuration of the loader repository for this deployment */
179    public LoaderRepositoryConfig repositoryConfig;
180    
181    /** The MBeanServer associated with the deployment */
182    private transient MBeanServer JavaDoc server;
183
184    /**
185     * CTOR
186     */

187    public DeploymentInfo(final URL JavaDoc url, final DeploymentInfo parent, final MBeanServer JavaDoc server)
188       throws DeploymentException
189    {
190       this.server = server;
191       // The key url the deployment comes from
192
this.url = url;
193
194       // this may be changed by deployers in case of directory and xml file following
195
this.watch = url;
196
197       // Whether we are part of a subdeployment or not
198
this.parent = parent;
199
200       // Is it a directory?
201
if (url.getProtocol().startsWith("file") && new File JavaDoc(url.getFile()).isDirectory())
202          this.isDirectory = true;
203
204       // Does it even exist?
205
if (!isDirectory)
206       {
207          try
208          {
209             url.openStream().close();
210          }
211          catch (Exception JavaDoc e)
212          {
213             throw new DeploymentException("url " + url + " could not be opened, does it exist?");
214          }
215       }
216
217       if (parent != null)
218       {
219          parent.subDeployments.add(this);
220          // Use the repository of our topmost parent
221
repositoryConfig = getTopRepositoryConfig();
222       }
223
224       // The "short name" for the deployment http://myserver/mybean.ear should yield "mybean.ear"
225
shortName = getShortName(url.getPath());
226       
227       // Do we have an XML descriptor only deployment?
228
isXML = shortName.toLowerCase().endsWith(".xml");
229       
230       // Do we have a stand-olone script deployment?
231
isScript = shortName.toLowerCase().endsWith(".bsh");
232    }
233
234    public MBeanServer JavaDoc getServer()
235    {
236       return server;
237    }
238    
239    public void setServer(MBeanServer JavaDoc server)
240    {
241       this.server = server;
242    }
243
244    /** Create a UnifiedClassLoader for the deployment that loads from
245     the localUrl and uses its parent deployments url as its orignal
246     url. Previously xml descriptors simply used the TCL but since the UCLs
247     are now registered as mbeans each must be unique.
248     */

249    public void createClassLoaders() throws Exception JavaDoc
250    {
251       // create a local classloader for local files, don't go with the UCL for ejb-jar.xml
252
if( localCl == null )
253          localCl = new URLClassLoader JavaDoc(new URL JavaDoc[] {localUrl});
254
255       /* Walk the deployment tree to find the parent deployment and obtain its
256        url to use as our URL from which this deployment unit originated. This
257        is used to determine permissions using the original URL namespace.
258        Also pick up the LoaderRepository from the topmost ancestor.
259       */

260       URL JavaDoc origUrl = url;
261       DeploymentInfo current = this;
262       while (current.parent != null)
263       {
264          current = current.parent;
265       }
266       origUrl = current.url;
267       repositoryConfig = current.repositoryConfig;
268       if( parent == null )
269       {
270          if( repositoryConfig == null )
271             repositoryConfig = new LoaderRepositoryConfig();
272          // Make sure the specified LoaderRepository exists.
273
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
274          log.debug("createLoaderRepository from config: "+repositoryConfig);
275          // the classes are passed to a UCL that will share the classes with the whole base
276

277          Object JavaDoc[] args = { isXML ? null : localUrl, origUrl, Boolean.TRUE };
278          String JavaDoc[] sig = { "java.net.URL", "java.net.URL", "boolean" };
279          ucl = (RepositoryClassLoader) server.invoke(repositoryConfig.repositoryName,
280             "newClassLoader",args, sig);
281       }
282       else
283       {
284          // Add a reference to the LoaderRepository
285
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
286          // Add the deployment URL to the parent UCL
287
ucl = parent.ucl;
288          ucl.addURL(localUrl);
289       }
290       // Add any library jars seen before the UCL was created
291
if( classpath.size() > 0 )
292       {
293          Iterator JavaDoc jars = classpath.iterator();
294          while( jars.hasNext() )
295          {
296             URL JavaDoc jar = (URL JavaDoc) jars.next();
297             ucl.addURL(jar);
298          }
299       }
300    }
301
302    /** Set the UnifiedLoaderRepository info for the deployment. This can only
303     * be called for the parent deployment, and must be done early in the
304     * Subdeployer init(DeploymentInfo) method prior to any class loading.
305     * @throws Exception
306     */

307    public void setRepositoryInfo(LoaderRepositoryConfig config)
308        throws Exception JavaDoc
309    {
310       if( parent != null )
311       {
312          log.warn("Only the root deployment can set the loader repository, "
313             + "ignoring config="+config);
314          return;
315       }
316
317       this.repositoryConfig = config;
318       // Recreate the ucl if it exists
319
if( ucl != null )
320       {
321          ucl.unregister();
322          // Make sure the specified LoaderRepository exists.
323
LoaderRepositoryFactory.createLoaderRepository(server, repositoryConfig);
324          log.debug("createLoaderRepository from config: "+repositoryConfig);
325          // the classes are passed to a UCL that will share the classes with the whole base
326

327          Object JavaDoc[] args = { isXML ? null : localUrl, url, Boolean.TRUE };
328          String JavaDoc[] sig = { "java.net.URL", "java.net.URL", "boolean" };
329          ucl = (RepositoryClassLoader) server.invoke(repositoryConfig.repositoryName,
330             "newClassLoader",args, sig);
331       }
332    }
333
334    /** All library jars referenced through either the manifest references
335     * or sar classpaths are added to the root DeploymentInfo class loader. This
336     * is neccessary to avoid IllegalAccessErrors due to classes in a pkg
337     * being split across jars
338     */

339    public void addLibraryJar(URL JavaDoc libJar)
340    {
341       DeploymentInfo current = this;
342       while (current.parent != null)
343       {
344          current = current.parent;
345       }
346       /* If the UCL exists add the jar to it else use the classpath to
347       indicate that the jars need to be added when the ucl is created.
348       */

349       if( current.ucl != null )
350          current.ucl.addURL(libJar);
351       else
352          classpath.add(libJar);
353    }
354
355    /** The the class loader repository name of the top most DeploymentInfo
356     */

357    public LoaderRepositoryConfig getTopRepositoryConfig()
358    {
359       LoaderRepositoryConfig topConfig = repositoryConfig;
360       DeploymentInfo info = this;
361       while( info.parent != null )
362       {
363          info = info.parent;
364          topConfig = info.repositoryConfig;
365       }
366       return topConfig;
367    }
368
369    /**
370     * getManifest returns (if present) the deployment's manifest
371     * it is lazy loaded to work from the localURL
372     */

373    public Manifest JavaDoc getManifest()
374    {
375       try
376       {
377          if (manifest == null)
378          {
379             File JavaDoc file = new File JavaDoc(localUrl.getFile());
380
381             if (file.isDirectory())
382             {
383                FileInputStream JavaDoc fis = new FileInputStream JavaDoc(new File JavaDoc(file, "META-INF/MANIFEST.MF"));
384                manifest = new Manifest JavaDoc(fis);
385                fis.close();
386             }
387             else if(isXML == false)// a jar
388
manifest = new JarFile JavaDoc(file).getManifest();
389          }
390
391          return manifest;
392       }
393       // It is ok to barf at any time in the above, means no manifest
394
catch (Exception JavaDoc ignored) { return null;}
395    }
396
397    public void cleanup()
398    {
399       // Remove the deployment UCL
400
if( parent == null && ucl != null )
401          ucl.unregister();
402       ucl = null;
403
404       // Remove any deployment specific repository
405
if ( repositoryConfig != null )
406       {
407          LoaderRepositoryFactory.destroyLoaderRepository(server,
408             repositoryConfig.repositoryName);
409       }
410
411       subDeployments.clear();
412       mbeans.clear();
413       context.clear();
414       if (localUrl == null || localUrl.equals(url))
415       {
416          log.debug("Not deleting localUrl, it is null or not a copy: " + localUrl);
417       }
418       else if (Files.delete(localUrl.getFile()))
419       {
420          log.debug("Cleaned Deployment: " + localUrl);
421       }
422       else
423       {
424          log.debug("Could not delete " + localUrl + " restart will delete it");
425       }
426
427       // Clean up references to other objects
428
localCl = null;
429       annotationsCl = null;
430       localUrl = null;
431       repositoryConfig = null;
432       watch = null;
433       parent = null;
434       manifest = null;
435       document = null;
436       metaData = null;
437       server = null;
438       classpath.clear();
439       state = DeploymentState.DESTROYED;
440       // Who is using this after clear?
441
// deployer = null;
442
}
443
444    /** The sortName concatenated with the canonical names of all parents. */
445    public String JavaDoc getCanonicalName()
446    {
447       String JavaDoc name = shortName;
448       if (parent != null)
449          name = parent.getCanonicalName() + "/" + name;
450       return name;
451    }
452
453    private String JavaDoc getShortName(String JavaDoc name)
454    {
455       if (name.endsWith("/")) name = name.substring(0, name.length() - 1);
456       name = name.substring(name.lastIndexOf("/") + 1);
457       return name;
458    }
459
460    public int hashCode()
461    {
462       return url.hashCode();
463    }
464
465    public boolean equals(Object JavaDoc other)
466    {
467       if (other instanceof DeploymentInfo)
468       {
469          return ((DeploymentInfo) other).url.equals(this.url);
470       }
471       return false;
472    }
473
474    public String JavaDoc toString()
475    {
476       StringBuffer JavaDoc s = new StringBuffer JavaDoc(super.toString());
477       s.append(" { url=" + url + " }\n");
478       s.append(" deployer: " + deployer + "\n");
479       s.append(" status: " + status + "\n");
480       s.append(" state: " + state + "\n");
481       s.append(" watch: " + watch + "\n");
482       s.append(" altDD: " + alternativeDD + "\n");
483       s.append(" lastDeployed: " + lastDeployed + "\n");
484       s.append(" lastModified: " + lastModified + "\n");
485       s.append(" mbeans:\n");
486       for (Iterator JavaDoc i = mbeans.iterator(); i.hasNext(); )
487       {
488          ObjectName JavaDoc o = (ObjectName JavaDoc)i.next();
489          try
490          {
491             String JavaDoc state = (String JavaDoc)server.getAttribute(o, "StateString");
492             s.append(" " + o + " state: " + state + "\n");
493          }
494          catch (Exception JavaDoc e)
495          {
496             s.append(" " + o + " (state not available)\n");
497          } // end of try-catch
498

499       } // end of for ()
500

501       return s.toString();
502    }
503 }
504
Popular Tags