KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb3 > EJB3Deployer


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.ejb3;
23
24 import java.io.DataInputStream JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.InputStreamReader JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.net.URLClassLoader JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Properties JavaDoc;
36 import javax.management.ObjectName JavaDoc;
37 import javax.naming.Context JavaDoc;
38 import javax.naming.InitialContext JavaDoc;
39 import javax.naming.NamingException JavaDoc;
40 import javax.naming.RefAddr JavaDoc;
41 import javax.naming.Reference JavaDoc;
42 import javax.naming.StringRefAddr JavaDoc;
43 import org.jboss.deployment.DeploymentException;
44 import org.jboss.deployment.DeploymentInfo;
45 import org.jboss.deployment.SubDeployer;
46 import org.jboss.deployment.SubDeployerSupport;
47 import org.jboss.metadata.MetaData;
48 import org.jboss.metadata.XmlFileLoader;
49 import org.jboss.mx.loading.LoaderRepositoryFactory;
50 import org.jboss.mx.util.MBeanProxyExt;
51 import org.jboss.mx.util.ObjectNameConverter;
52 import org.jboss.system.ServiceControllerMBean;
53 import org.jboss.util.file.ArchiveBrowser;
54 import org.jboss.util.file.ClassFileFilter;
55 import org.w3c.dom.Element JavaDoc;
56
57 import javassist.bytecode.AnnotationsAttribute;
58 import javassist.bytecode.ClassFile;
59
60 /**
61  * Deployer for Aspects
62  *
63  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
64  * @version $Revision: 58015 $
65  */

66 public class EJB3Deployer extends SubDeployerSupport
67    implements SubDeployer, EJB3DeployerMBean
68 {
69    private ServiceControllerMBean serviceController;
70
71    /** A map of current deployments */
72    private HashMap JavaDoc deployments = new HashMap JavaDoc();
73
74    /** Hold a proxy reference to myself, used when registering to MainDeployer */
75    private SubDeployer thisProxy;
76
77    private Properties JavaDoc DefaultProperties;
78
79    private HashSet JavaDoc ignoredJarsSet;
80    private HashMap JavaDoc<DeploymentInfo, String JavaDoc> jmxNames = new HashMap JavaDoc();
81
82    /**
83     * Default CTOR used to set default values to the Suffixes and RelativeOrder
84     * attributes. Those are read at subdeployer registration time by the MainDeployer
85     * to alter its SuffixOrder.
86     */

87    public EJB3Deployer()
88    {
89       setSuffixes(new String JavaDoc[]{".jar", ".ejb3", ".par"});
90       setRelativeOrder(400); // before old EJB 2.1 deployer
91
}
92
93    public static boolean hasFile(DeploymentInfo di, String JavaDoc filePath)
94    {
95       String JavaDoc urlStr = di.url.getFile();
96       try
97       {
98          URL JavaDoc dd = di.localCl.findResource(filePath);
99          if (dd != null)
100          {
101
102             // If the DD url is not a subset of the urlStr then this is coming
103
// from a jar referenced by the deployment jar manifest and the
104
// this deployment jar it should not be treated as persistence
105
if (di.localUrl != null)
106             {
107                urlStr = di.localUrl.toString();
108             }
109
110             String JavaDoc ddStr = dd.toString();
111             if (ddStr.indexOf(urlStr) >= 0)
112             {
113                return true;
114             }
115          }
116       }
117       catch (Exception JavaDoc ignore)
118       {
119       }
120       return false;
121    }
122
123    public static boolean hasPersistenceXml(DeploymentInfo di)
124    {
125       return hasFile(di, "META-INF/persistence.xml");
126    }
127
128    public static boolean has30EjbJarXml(DeploymentInfo di)
129    {
130       if (!hasFile(di, "META-INF/ejb-jar.xml")) return false;
131       InputStream JavaDoc ddStream = di.localCl.getResourceAsStream("META-INF/ejb-jar.xml");
132
133       return has30EjbJarXml(ddStream);
134    }
135
136    public static boolean has30EjbJarXml(InputStream JavaDoc ddStream)
137    {
138       try
139       {
140          // look for version="3.0" in the file
141
byte[] stringToFind = "version=\"3.0\"".getBytes();
142          InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(ddStream);
143          try
144          {
145             int idx = 0;
146             int len = stringToFind.length;
147             while (reader.ready())
148             {
149                int read = reader.read();
150                if (read == stringToFind[idx])
151                {
152                   idx++;
153                   if (idx == len)
154                   {
155                      return true;
156                   }
157                }
158                else
159                {
160                   idx = 0;
161                }
162             }
163
164          }
165          finally
166          {
167             try
168             {
169                reader.close();
170                ddStream.close();
171             }
172             catch (IOException JavaDoc ignored)
173             {
174             }
175          }
176       }
177       catch (Exception JavaDoc ignore)
178       {
179       }
180       return false;
181    }
182
183    protected boolean hasOnlyJbossXml(DeploymentInfo di)
184    {
185       if (!hasFile(di, "META-INF/ejb-jar.xml")
186          && hasFile(di, "META-INF/jboss.xml"))
187       {
188          return true;
189       }
190       return false;
191    }
192
193    public boolean hasEjbAnnotation(DeploymentInfo di)
194    {
195       Iterator JavaDoc it = ArchiveBrowser.getBrowser(di.url, new ClassFileFilter());
196       try
197       {
198          while (it.hasNext())
199          {
200             InputStream JavaDoc stream = (InputStream JavaDoc) it.next();
201             DataInputStream JavaDoc dstream = new DataInputStream JavaDoc(stream);
202             ClassFile cf = null;
203             try
204             {
205                cf = new ClassFile(dstream);
206                AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag);
207                if (visible != null)
208                {
209                   if (EJB3Util.isStateless(visible)) return true;
210                   if (EJB3Util.isStatefulSession(visible)) return true;
211                   if (EJB3Util.isMessageDriven(visible)) return true;
212                   if (EJB3Util.isConsumer(visible)) return true;
213                   if (EJB3Util.isService(visible)) return true;
214                }
215             }
216             finally
217             {
218                dstream.close();
219                stream.close();
220             }
221          }
222       }
223       catch (IOException JavaDoc e)
224       {
225          throw new RuntimeException JavaDoc(e);
226       }
227       return false;
228    }
229
230    /**
231     * Returns true if this deployer can deploy the given DeploymentInfo.
232     *
233     * @return True if this deployer can deploy the given DeploymentInfo.
234     * @jmx:managed-operation
235     */

236    public boolean accepts(DeploymentInfo di)
237    {
238       String JavaDoc urlStr = di.url.getFile();
239       if (urlStr.endsWith(".ejb3") || urlStr.endsWith(".ejb3/") || urlStr.endsWith(".par") || urlStr.endsWith(".par/"))
240       {
241          return true;
242       }
243       // To be accepted the deployment's root name must end in jar
244
if (!urlStr.endsWith(".jar") && !urlStr.endsWith(".jar/"))
245       {
246          return false;
247       }
248
249       if (ignoredJarsSet.contains(di.shortName))
250       {
251          return false;
252       }
253
254       if (hasPersistenceXml(di)) return true;
255       if (hasOnlyJbossXml(di)) return true;
256       if (has30EjbJarXml(di)) return true;
257       if (hasEjbAnnotation(di)) return true;
258
259
260       return false;
261    }
262
263    public Properties JavaDoc getDefaultProperties()
264    {
265       return DefaultProperties;
266    }
267
268    public void setJarsIgnoredForScanning(JarsIgnoredForScanningMBean mbean)
269    {
270       ignoredJarsSet = mbean.getIgnoredJarsSet();
271    }
272
273    /**
274     * Overriden to set the hibernate.bytecode.provider from the
275     *
276     * @throws Exception
277     */

278    protected void createService() throws Exception JavaDoc
279    {
280       URL JavaDoc propsUrl = this.getClass().getClassLoader().getResource("META-INF/persistence.properties");
281       DefaultProperties = new Properties JavaDoc();
282       DefaultProperties.load(propsUrl.openStream());
283       log.debug("Default persistence.properties: " + DefaultProperties);
284       /* Current hack to establish the hibernate bytecode provider from the
285       externalized persistence.properties
286       */

287       String JavaDoc bcprovider = DefaultProperties.getProperty("hibernate.bytecode.provider", "javassist");
288       System.setProperty("hibernate.bytecode.provider", bcprovider);
289       super.createService();
290    }
291
292    /**
293     * Get a reference to the ServiceController
294     */

295    protected void startService() throws Exception JavaDoc
296    {
297       serviceController = (ServiceControllerMBean)
298               MBeanProxyExt.create(ServiceControllerMBean.class,
299                                    ServiceControllerMBean.OBJECT_NAME, server);
300
301       // make a proxy to myself, so that calls from the MainDeployer
302
// can go through the MBeanServer, so interceptors can be added
303
thisProxy = (SubDeployer)
304               MBeanProxyExt.create(SubDeployer.class, super.getServiceName(), super.getServer());
305
306       // register with the main deployer
307
mainDeployer.addDeployer(thisProxy);
308
309       // todo remove when we merge older model of ENC
310
InitialContext JavaDoc iniCtx = new InitialContext JavaDoc();
311       initializeJavaComp(iniCtx);
312    }
313
314    public static void initializeJavaComp(InitialContext JavaDoc iniCtx)
315            throws NamingException JavaDoc
316    {
317       RefAddr JavaDoc refAddr = new StringRefAddr JavaDoc("nns", "ENC-EJB3");
318       Reference JavaDoc envRef = new Reference JavaDoc("javax.naming.Context", refAddr, ThreadLocalENCFactory.class.getName(), null);
319       Context JavaDoc ctx = (Context JavaDoc) iniCtx.lookup("java:");
320       ctx.rebind("comp.ejb3", envRef);
321    }
322
323    /**
324     * Implements the template method in superclass. This method stops all the
325     * applications in this server.
326     */

327    protected void stopService() throws Exception JavaDoc
328    {
329       for (Iterator JavaDoc modules = deployments.values().iterator();
330            modules.hasNext();)
331       {
332          DeploymentInfo di = (DeploymentInfo) modules.next();
333          stop(di);
334       } // avoid concurrent modification exception
335
for (Iterator JavaDoc modules = new ArrayList JavaDoc(deployments.values()).iterator();
336            modules.hasNext();)
337       {
338          DeploymentInfo di = (DeploymentInfo) modules.next();
339          destroy(di);
340       }
341       deployments.clear();
342
343       // deregister with MainDeployer
344
mainDeployer.removeDeployer(thisProxy);
345
346       serviceController = null;
347    }
348
349    public void init(DeploymentInfo di) throws DeploymentException
350    {
351       try
352       {
353          if( di.url.getProtocol().equalsIgnoreCase("file") )
354          {
355             File JavaDoc file = new File JavaDoc(di.url.getFile());
356
357             if( !file.isDirectory() )
358             {
359                // If not directory we watch the package
360
di.watch = di.url;
361             }
362             else
363             {
364                // If directory we watch the xml files
365
di.watch = new URL JavaDoc(di.url, "META-INF/ejb-jar.xml");
366             }
367          }
368          else
369          {
370             // We watch the top only, no directory support
371
di.watch = di.url;
372          }
373          
374          XmlFileLoader xfl = new XmlFileLoader();
375          InputStream JavaDoc in = di.localCl.getResourceAsStream("META-INF/jboss.xml");
376          if( in != null )
377          {
378             try
379             {
380                Element JavaDoc jboss = xfl.getDocument(in, "META-INF/jboss.xml").getDocumentElement();
381                // Check for a ejb level class loading config
382
Element JavaDoc loader = MetaData.getOptionalChild(jboss, "loader-repository");
383                if( loader != null )
384                {
385                   LoaderRepositoryFactory.LoaderRepositoryConfig config =
386                         LoaderRepositoryFactory.parseRepositoryConfig(loader);
387                   di.setRepositoryInfo(config);
388                }
389                
390                Element JavaDoc jmxNameElement = MetaData.getOptionalChild(jboss, "jmx-name");
391                if (jmxNameElement != null)
392                {
393                   jmxNames.put(di, jmxNameElement.getChildNodes().item(0).getNodeValue());
394                }
395             }
396             finally
397             {
398                in.close();
399             }
400          }
401       }
402       catch (Exception JavaDoc e)
403       {
404          if (e instanceof DeploymentException)
405          {
406             throw (DeploymentException) e;
407          }
408          throw new DeploymentException( "failed to initialize", e );
409       }
410
411       // invoke super-class initialization
412
super.init(di);
413    }
414
415    public synchronized void create(DeploymentInfo di) throws DeploymentException
416    {
417       log.debug("create, " + di.shortName);
418
419       try
420       {
421          // initialize the annotations loader
422
URL JavaDoc loaderURL = (di.localUrl != null ? di.localUrl : di.url);
423          di.annotationsCl = new URLClassLoader JavaDoc(new URL JavaDoc[]{loaderURL}, di.ucl);
424
425          Ejb3Module ejbModule = new Ejb3Module(di);
426          String JavaDoc name = jmxNames.get(di);
427          if (name == null)
428             name = Ejb3Module.BASE_EJB3_JMX_NAME + ",module=" + di.shortName;
429          // Build an escaped JMX name including deployment shortname
430
ObjectName JavaDoc ejbModuleName = ObjectNameConverter.convert(name);
431          // Check that the name is not registered
432
if (server.isRegistered(ejbModuleName) == true)
433          {
434             log.debug("The EJBModule name: " + ejbModuleName
435                       + "is already registered, adding uid=" + System.identityHashCode(ejbModule));
436             name = name + ",uid=" + System.identityHashCode(ejbModule);
437             ejbModuleName = ObjectNameConverter.convert(name);
438          }
439          server.registerMBean(ejbModule, ejbModuleName);
440          di.deployedObject = ejbModuleName;
441          log.debug("Deploying: " + di.url);
442          // Invoke the create life cycle method
443
serviceController.create(di.deployedObject);
444       }
445       catch (Exception JavaDoc e)
446       {
447          throw new DeploymentException("Error during create of EjbModule: "
448                                        + di.url, e);
449       }
450       super.create(di);
451    }
452
453    public synchronized void start(DeploymentInfo di)
454            throws DeploymentException
455    {
456       try
457       {
458          // Start application
459
log.debug("start application, deploymentInfo: " + di +
460                    ", short name: " + di.shortName +
461                    ", parent short name: " +
462                    (di.parent == null ? "null" : di.parent.shortName));
463          serviceController.start(di.deployedObject);
464          log.info("Deployed: " + di.url); // Register deployment. Use the application name in the hashtable
465
// FIXME: this is obsolete!! (really?!)
466
deployments.put(di.url, di);
467       }
468       catch (Exception JavaDoc e)
469       {
470          stop(di);
471          destroy(di);
472          throw new DeploymentException("Could not deploy " + di.url, e);
473       }
474       super.start(di);
475    }
476
477    public void stop(DeploymentInfo di)
478            throws DeploymentException
479    {
480       log.debug("init, " + di.shortName);
481       try
482       {
483          serviceController.stop(di.deployedObject);
484       }
485       catch (Exception JavaDoc e)
486       {
487          throw new DeploymentException("problem stopping ejb module: " +
488                                        di.url, e);
489       }
490       
491       super.stop(di);
492    }
493
494    public void destroy(DeploymentInfo di)
495            throws DeploymentException
496    {
497       // FIXME: If the put() is obsolete above, this is obsolete, too
498
deployments.remove(di.url);
499       try
500       {
501          serviceController.destroy(di.deployedObject);
502          serviceController.remove(di.deployedObject);
503       }
504       catch (Exception JavaDoc e)
505       {
506          throw new DeploymentException("problem destroying ejb module: " +
507                                        di.url, e);
508       }
509       
510       jmxNames.remove(di);
511       
512       super.destroy(di);
513    }
514 }
515
Popular Tags