KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > hibernate > har > HARDeployer


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.hibernate.har;
8
9 import java.io.File JavaDoc;
10 import java.net.URL JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import javax.management.MBeanServer JavaDoc;
15 import javax.management.MalformedObjectNameException JavaDoc;
16 import javax.management.ObjectName JavaDoc;
17 import javax.management.Attribute JavaDoc;
18 import javax.management.MBeanInfo JavaDoc;
19
20 import org.jboss.deployment.DeploymentInfo;
21 import org.jboss.deployment.SubDeployerSupport;
22 import org.jboss.deployment.DeploymentException;
23 import org.jboss.system.ServiceControllerMBean;
24 import org.jboss.mx.util.MBeanProxyExt;
25 import org.jboss.mx.util.ObjectNameFactory;
26 import org.jboss.hibernate.jmx.Hibernate;
27
28 /**
29  * Deployer for Hibernate <tt>har</tt> archives. A Hibernate archive
30  * is expected to have a .har extension and include:<ul>
31  * <li> <tt>hibernate-service.xml</tt>
32  * <li> persistent classes
33  * <li> <tt>hbm.xml</tt> mapping documents.</ul>
34  *
35  * @jmx:mbean
36  * name="jboss.har:service=HARDeployer"
37  * extends="org.jboss.deployment.SubDeployerMBean"
38  *
39  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
40  * @author <a HREF="mailto:steve@hibernate.org">Steve Ebersole</a>
41  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
42  *
43  * @version <tt>$Revision: 1.2.2.4 $</tt>
44  */

45 public class HARDeployer extends SubDeployerSupport
46    implements HARDeployerMBean
47 {
48    private static final ObjectName JavaDoc OBJECT_NAME = ObjectNameFactory.create("jboss.har:service=HARDeployer");
49    private static final String JavaDoc DESCRIPTOR_NAME = "hibernate-service.xml";
50    private static final String JavaDoc RELATIVE_DESCRIPTOR_URL = "META-INF/" + DESCRIPTOR_NAME;
51
52    private ServiceControllerMBean serviceController;
53
54    /** A map of current deployments. */
55    private HashMap JavaDoc deployments = new HashMap JavaDoc();
56
57    /** A flag indicating if deployment descriptors should be validated */
58    private boolean validateDTDs;
59
60    /**
61     * Default CTOR used to set default values to the Suffixes and RelativeOrder
62     * attributes. Those are read at subdeployer registration time by the MainDeployer
63     * to alter its SuffixOrder.
64     */

65    public HARDeployer()
66    {
67       setSuffixes( new String JavaDoc[] { ".har" } );
68       setRelativeOrder( RELATIVE_ORDER_400 );
69    }
70    
71    /**
72     * Returns the deployed applications.
73     *
74     * @jmx:managed-operation
75     */

76    public Iterator JavaDoc getDeployedApplications()
77    {
78       return deployments.values().iterator();
79    }
80
81    protected ObjectName JavaDoc getObjectName(MBeanServer JavaDoc server, ObjectName JavaDoc name)
82       throws MalformedObjectNameException JavaDoc
83    {
84       return name == null ? OBJECT_NAME : name;
85    }
86
87    /**
88     * Get a reference to the ServiceController
89     */

90    protected void startService() throws Exception JavaDoc
91    {
92       serviceController = ( ServiceControllerMBean ) MBeanProxyExt.create(
93               ServiceControllerMBean.class,
94                ServiceControllerMBean.OBJECT_NAME, server
95       );
96
97       // register with MainDeployer
98
super.startService();
99    }
100
101    /**
102     * Implements the template method in superclass. This method stops all the
103     * applications in this server.
104     */

105    protected void stopService() throws Exception JavaDoc
106    {
107       Iterator JavaDoc modules = deployments.values().iterator();
108       while ( modules.hasNext() )
109       {
110          DeploymentInfo di = (DeploymentInfo)modules.next();
111          stop(di);
112       }
113
114       // avoid concurrent modification exception
115
modules = new ArrayList JavaDoc( deployments.values() ).iterator();
116       while ( modules.hasNext() )
117       {
118          DeploymentInfo di = (DeploymentInfo)modules.next();
119          destroy(di);
120       }
121       deployments.clear();
122
123       // deregister with MainDeployer
124
super.stopService();
125
126       serviceController = null;
127    }
128
129    /**
130     * Get the flag indicating that ejb-jar.dtd, jboss.dtd &amp;
131     * jboss-web.dtd conforming documents should be validated
132     * against the DTD.
133     *
134     * @jmx:managed-attribute
135     */

136    public boolean getValidateDTDs()
137    {
138       return validateDTDs;
139    }
140
141    /**
142     * Set the flag indicating that ejb-jar.dtd, jboss.dtd &amp;
143     * jboss-web.dtd conforming documents should be validated
144     * against the DTD.
145     *
146     * @jmx:managed-attribute
147     */

148    public void setValidateDTDs(boolean validate)
149    {
150       this.validateDTDs = validate;
151    }
152
153    // -------------------------------------------------------------------------
154
// Sub-deployable bit ------------------------------------------------------
155
// This is all essentially saying that the hibernate-service.xml file
156
// consitutes a nested deployment (i.e., isDeployable) such that a
157
// subdeployment is generated for that file by itself. The whole
158
// purpose of this fact is to get SARDeployer to pick up the service
159
// xml file and parse it. At some point this gets "linked back" to our
160
// DeploymentInfo.subDeployments so that we have access to it.
161
//
162
// TODO : this all seems very hacky.
163
// Would prefer having SARDeployer xml parsing logic encapsulated so that it
164
// can just get used directly from here.
165
protected void processNestedDeployments(DeploymentInfo di) throws DeploymentException
166    {
167       super.processNestedDeployments( di );
168    }
169
170    protected void deployUrl(DeploymentInfo di, URL JavaDoc url, String JavaDoc name) throws DeploymentException
171    {
172       super.deployUrl( di, url, name );
173    }
174
175    public boolean isDeployable(String JavaDoc name, URL JavaDoc url)
176    {
177       // Allow nested jars to get deployed.
178
//
179
// We also mark the 'hibernate-service.xml' file as deployable so that
180
// the SARDeployer can pick it up and parse its content as described above; yick!
181
log.debug( "Checking deployability of [name=" + name + ", url=" + url.getFile() + "]" );
182       return name.endsWith( ".jar" ) || name.endsWith( RELATIVE_DESCRIPTOR_URL );
183    }
184    // -------------------------------------------------------------------------
185

186    /**
187     * The HARDeployer accepts either archives ending in '.har' or exploded
188     * directories (with name ending in '.har/'). Furthermore, the deployment
189     * must contain a file named 'META-INF/hibernate-service.xml' in order to
190     * be accepted.
191     *
192     * @param di The deployment info for the deployment to be checked for
193     * acceptance.
194     * @return True if the conditions mentioned above hold true; false otherwise.
195     */

196    public boolean accepts(DeploymentInfo di)
197    {
198       // To be accepted the deployment's root name must end in .har
199
String JavaDoc urlStr = di.url.getFile();
200       if ( !urlStr.endsWith( ".har" ) && !urlStr.endsWith( ".har/" ) )
201       {
202          return false;
203       }
204
205       // However the har must also contain a ${RELATIVE_DESCRIPTOR_URL}
206
boolean accept = false;
207       try
208       {
209          URL JavaDoc dd = di.localCl.findResource( RELATIVE_DESCRIPTOR_URL );
210          if ( dd != null )
211          {
212             // If the DD url is not a subset of the urlStr then this is coming
213
// from a jar referenced by the deployment jar manifest and the
214
// this deployment jar it should not be treated as an ejb-jar
215
if ( di.localUrl != null )
216             {
217                urlStr = di.localUrl.toString();
218             }
219
220             String JavaDoc ddStr = dd.toString();
221             if( ddStr.indexOf( urlStr ) >= 0 )
222             {
223                accept = true;
224             }
225          }
226       }
227       catch( Exception JavaDoc ignore )
228       {
229       }
230
231       log.debug( "accept> url=" + di.url + ", accepted=" + accept );
232
233       return accept;
234    }
235
236    /**
237     * Initialize the given deployment. Overriden to perform custom watch logic.
238     *
239     * @param di The deployment to be initialized.
240     * @throws DeploymentException
241     */

242    public void init(DeploymentInfo di) throws DeploymentException
243    {
244       log.debug( "Deploying HAR; init; " + di );
245       try
246       {
247          if( "file".equalsIgnoreCase( di.url.getProtocol() ) )
248          {
249             File JavaDoc file = new File JavaDoc( di.url.getFile() );
250
251             if ( !file.isDirectory() )
252             {
253                // If not directory we watch the package
254
di.watch = di.url;
255             }
256             else
257             {
258                // If directory we watch the xml files
259
di.watch = new URL JavaDoc( di.url, DESCRIPTOR_NAME );
260             }
261          }
262          else
263          {
264             // We watch the top only, no directory support
265
di.watch = di.url;
266          }
267       }
268       catch( Exception JavaDoc e )
269       {
270          if ( e instanceof DeploymentException )
271          {
272             throw ( DeploymentException ) e;
273          }
274          throw new DeploymentException( "failed to initialize", e );
275       }
276
277       // invoke super-class initialization
278
super.init( di );
279    }
280
281    public synchronized void create(DeploymentInfo di) throws DeploymentException
282    {
283       log.debug( "Deploying HAR; create; " + di );
284       super.create( di );
285
286       // Impl note: this, again, is relying on the fact that the SARDeployer has
287
// already parsed the hibernate-service.xml file and created any defined
288
// mbeans; these are then available through the 'subDeployments' attribute
289
// of the DeploymentInfo related to the overall har file. clear as mud? :)
290
//
291
// *there should only ever be one sub-deployment here...
292
Iterator JavaDoc subdeployments = di.subDeployments.iterator();
293       while ( subdeployments.hasNext() )
294       {
295          DeploymentInfo nested = ( DeploymentInfo ) subdeployments.next();
296          log.debug( "Checking sub-deployment [" + nested.url + "] for descriptor-name" );
297
298          // check each sub-deployment to find the one relating to our
299
// hibernate-service.xml file.
300
if ( nested.url.getFile().endsWith( DESCRIPTOR_NAME ) )
301          {
302             log.debug( "Attempting to locate HibernateMBean in sub-deployment [" + nested.url + "]" );
303             Iterator JavaDoc mbeans = nested.mbeans.iterator();
304
305             // For all the mbeans defined on our service descriptor, locate the
306
// Hibernate mbean and pass it the har deployment's url so that
307
// it can auto detect the mapping files.
308
while ( mbeans.hasNext() )
309             {
310                ObjectName JavaDoc service = ( ObjectName JavaDoc ) mbeans.next();
311                log.debug( "Testing [" + service + "] as HibernateMBean" );
312                if ( isHibernateMBean( service ) )
313                {
314                   log.debug( "Located HibernateMBean" );
315                   Attribute JavaDoc attr = new Attribute JavaDoc( "HarUrl", di.url );
316                   try
317                   {
318                      server.setAttribute( service, attr );
319                   }
320                   catch( Exception JavaDoc e )
321                   {
322                      throw new DeploymentException( "Failed to set HarUrl attribute: " + e.getMessage(), e );
323                   }
324                }
325             }
326             break;
327          }
328       }
329    }
330
331    public synchronized void start(DeploymentInfo di) throws DeploymentException
332    {
333       log.debug( "Deploying HAR; start; " + di );
334       super.start( di );
335    }
336
337    public void stop(DeploymentInfo di) throws DeploymentException
338    {
339       log.debug( "Undeploying HAR; stop; " + di );
340       try
341       {
342          serviceController.stop(di.deployedObject);
343       }
344       catch(Exception JavaDoc e)
345       {
346          throw new DeploymentException("problem stopping har module: " + di.url, e);
347       }
348       super.stop(di);
349    }
350
351    public void destroy(DeploymentInfo di) throws DeploymentException
352    {
353       log.debug( "Undeploying HAR; destroy; " + di );
354       // FIXME: If the put() is obsolete above, this is obsolete, too
355
deployments.remove(di.url);
356
357       try
358       {
359          serviceController.destroy(di.deployedObject);
360          serviceController.remove(di.deployedObject);
361       }
362       catch(Exception JavaDoc e)
363       {
364          throw new DeploymentException("problem destroying har module: " + di.url, e);
365       }
366       super.destroy( di );
367    }
368
369    private boolean isHibernateMBean(ObjectName JavaDoc service)
370    {
371       try
372       {
373          MBeanInfo JavaDoc serviceInfo = server.getMBeanInfo( service );
374          return Hibernate.class.getName().equals( serviceInfo.getClassName() );
375       }
376       catch( Throwable JavaDoc t )
377       {
378          log.warn( "Unable to determine whether MBean [" + service + "] is Hibernate MBean" );
379          return false;
380       }
381    }
382 }
383
Popular Tags