KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > deployment > backend > EJBCompiler


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * EJBCompiler.java
26  *
27  * Created on February 23, 2002, 12:02 PM
28  *
29  * @author bnevins
30  * <BR> <I>$Source: /cvs/glassfish/appserv-core/src/java/com/sun/enterprise/deployment/backend/EJBCompiler.java,v $
31  *
32  */

33
34 package com.sun.enterprise.deployment.backend;
35
36 import java.io.File JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.logging.Level JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42 import javax.enterprise.deploy.shared.ModuleType JavaDoc;
43
44 import com.sun.enterprise.util.io.FileUtils;
45 import com.sun.enterprise.util.StringUtils;
46 import com.sun.enterprise.util.zip.ZipItem;
47
48 import com.sun.enterprise.instance.BaseManager;
49 import com.sun.enterprise.instance.AppsManager;
50 import com.sun.enterprise.instance.EjbModulesManager;
51 import com.sun.enterprise.instance.WebModulesManager;
52 import com.sun.enterprise.instance.ModulesManager;
53 import com.sun.enterprise.instance.UniqueIdGenerator;
54
55 import com.sun.enterprise.loader.EJBClassPathUtils;
56 import com.sun.ejb.codegen.IASEJBC;
57 import com.sun.ejb.codegen.IASEJBCTimes;
58 import com.sun.enterprise.util.i18n.StringManager;
59 import com.sun.enterprise.loader.EJBClassLoader;
60
61
62 import com.sun.enterprise.security.acl.RoleMapper;
63 import com.sun.enterprise.deployment.Application;
64 import com.sun.enterprise.deployment.Descriptor;
65 import com.sun.enterprise.deployment.EjbBundleDescriptor;
66 import com.sun.enterprise.deployment.EjbDescriptor;
67 import com.sun.enterprise.deployment.BundleDescriptor;
68 import com.sun.enterprise.deployment.RootDeploymentDescriptor;
69 import com.sun.enterprise.deployment.util.ModuleDescriptor;
70 import com.sun.enterprise.deployment.phasing.DeploymentServiceUtils;
71 import com.sun.enterprise.security.application.EJBSecurityManager;
72
73 import java.io.IOException JavaDoc;
74 import org.xml.sax.SAXParseException JavaDoc;
75 import com.sun.enterprise.config.ConfigException;
76
77 /**
78  * This class is responsible mainly for executing ejbc.
79  * It also does the following:
80  * <pre>
81  * - constructs the class loader for the deployed app
82  * - loads the deployment descriptors
83  * - calls ejbc
84  * - sets the unique id
85  * - writes the deployment descriptors
86  *
87  * classpath: Ejbc reads the target instance's classpath-prefix and
88  * classpath-suffix via config context. It creates a class loader
89  * hierarchy based on these class paths, common class loader urls
90  * ($INSTANCE/lib/classes:$INSTANCE/lib/*.jar:$INSTANCE/lib/*.zip)
91  * and the application's urls.
92  *
93  * BootStrap<-System<-Common<-Share<-Ejb<-Servlet<-Jasper [Admin Server]
94  * |
95  * |<-(classpath-prefix+classpath-suffix)<-Common<-Shared<-Ejb [EJBC]
96  *
97  * Note that System classpath is shared between the two hierarchy.
98  * According to the architect, end users are not expected to replace the
99  * Application Server's jar (for example, appserv-rt.jar, etc). So, it is
100  * sufficient to include the classpath-prefix and classpath-suffix in the
101  * ejbc class loader hierarchy. Any system level jar should be replaced
102  * accross all server instances.
103  *
104  * S1AS8 Change:
105  * Deployment no longer needs to pick up class paths from target
106  * server instance. Deployment class paths contains only the DAS's
107  * class path plus the whole application paths.
108  *
109  * rmic-options: Ejbc reads rmic options from server xml. If none found, it
110  * gets the default from DTD.
111  *
112  * javac-options: Ejbc reads javac options from server xml. It supports
113  * the "-g" and "-O" options.
114  * </pre>
115  */

116 public class EJBCompiler
117 {
118     /**
119      *Returns new instance of EJBCompiler, using the deployment request's classpath list as the classpath
120      *to be used during compilation.
121      *
122      */

123     public EJBCompiler
124     (
125         String JavaDoc name,
126         File JavaDoc srcDir,
127         File JavaDoc oldSrcDir,
128         File JavaDoc stubsDir,
129         File JavaDoc oldStubsDir,
130         BaseManager manager,
131         DeploymentRequest request,
132         IASEJBCTimes timing
133
134     ) throws IASDeploymentException
135     
136     {
137         this(name, srcDir, oldSrcDir, stubsDir, oldStubsDir, manager, request, timing, request.getCompleteClasspath());
138     }
139
140     /**
141      *Returns new instance of EJBCompiler, accepting an alternate classpath List to be used during compilation.
142      *<p>
143      *This added constructor supports the fix for bug 4980750 so WebModuleDeployer can specify an adjusted
144      *classpath for use during compilation.
145      */

146     public EJBCompiler
147         (
148         String JavaDoc name,
149         File JavaDoc srcDir,
150         File JavaDoc oldSrcDir,
151         File JavaDoc stubsDir,
152         File JavaDoc oldStubsDir,
153         BaseManager manager,
154         DeploymentRequest request,
155         IASEJBCTimes timing,
156         java.util.List JavaDoc classpathForCompilation
157
158     ) throws IASDeploymentException
159
160     {
161         assert StringUtils.ok(name);
162         assert FileUtils.safeIsDirectory(srcDir);
163         assert FileUtils.safeIsDirectory(oldSrcDir);
164         assert FileUtils.safeIsDirectory(stubsDir);
165         assert FileUtils.safeIsDirectory(oldStubsDir);
166         assert manager != null;
167         assert request != null;
168         assert timing != null;
169
170         try
171         {
172             this.name = name;
173             this.request = request;
174             this.classpathForCompilation = classpathForCompilation;
175
176             // context used during code gen
177
this.ejbcContext = new EjbcContextImpl();
178             ejbcContext.setSrcDir(srcDir);
179             ejbcContext.setOldSrcDir(oldSrcDir);
180             ejbcContext.setStubsDir(stubsDir);
181             ejbcContext.setOldStubsDir(oldStubsDir);
182             ejbcContext.setTiming(timing);
183             ejbcContext.setRmicOptions( manager.getRmicOptions() );
184             ejbcContext.setJavacOptions( manager.getJavacOptions() );
185             ejbcContext.setOptionalArguments(this.request.getOptionalArguments());
186             ejbcContext.setDeploymentRequest(request);
187
188             if(manager instanceof ModulesManager)
189             {
190                 moduleManager = (ModulesManager)manager;
191                 appManager = null;
192             }
193             else if(manager instanceof AppsManager)
194             {
195                 appManager = (AppsManager)manager;
196                 moduleManager = null;
197             }
198             else
199                 assert (false);
200         }
201         catch(Throwable JavaDoc t)
202         {
203             throw wrapException(t);
204         }
205     }
206
207     ///////////////////////////////////////////////////////////////////////////
208

209     public ZipItem[] compile() throws IASDeploymentException
210     {
211         ZipItem[] clientStubs = null;
212         try
213         {
214             if(request.getNoEJBC())
215             {
216                 _logger.info( "********** EJBC Skipped! ************" );
217                 return new ZipItem[] {};
218             }
219             
220             if(appManager != null)
221             {
222                 clientStubs = preDeployApp();
223             }
224             else
225             {
226                 clientStubs = preDeployModule();
227             }
228
229             Application app = ejbcContext.getDescriptor();
230             if (app != null)
231             {
232                 for (Iterator JavaDoc iter = app.getEjbDescriptors().iterator();
233             iter.hasNext();)
234         {
235             //translate deployment descriptor to load PolicyConfiguration
236
EJBSecurityManager.loadPolicyConfiguration((EjbDescriptor)iter.next());
237                 }
238             }
239         }
240         catch(Throwable JavaDoc t)
241         {
242             throw wrapException(t);
243         } finally {
244             this.ejbcContext.cleanup();
245         }
246
247         return clientStubs;
248     }
249
250     /**
251      * EJBC for an application. This is called from the deployment backend.
252      * clientDstJar is the EAR that was deployed. It has been saved in
253      * classLoadable format (i.e. all classes in all jars contained in the EAR
254      * have been expanded out from the root of the EAR so that they can be
255      * loaded by the JarClassLoader).
256      *
257      * <pre>
258      *
259      * This method makes the following assumptions:
260      * - the deployment descriptor xmls are registered with Config
261      * - the class paths are registered with Config
262      *
263      * In case of re-deployment, the following steps should happen before:
264      * - the src dir from previous deployment should be under app_N-1
265      * (ex. /applications/j2ee-apps/petstore_1)
266      * - rename the stubs dir from previous deployment (ex. /stub/pet-old)
267      * - explode the ear file (ex. /applications/j2ee-apps/petstore_2)
268      * - register the deployment descriptor xml with config
269      * - register the class path with config
270      *
271      * After successful completion of this method, the old src and sutbs
272      * directories may be deleted.
273      *
274      * </pre>
275      *
276      * @return the client stubs as zip entries; these entries are added to
277      * the client jar
278      *
279      * @exception Exception error while running ejbc
280      */

281     private ZipItem[] preDeployApp() throws Exception JavaDoc
282     {
283         ZipItem[] clientStubs = null;
284
285         Application application = request.getDescriptor();
286
287         String JavaDoc appRoot = ejbcContext.getSrcDir().getCanonicalPath();
288         setEjbClasspath(request.getModuleClasspath());
289         ejbcContext.setDescriptor(application);
290
291         /*
292          *Bug 4980750 - See also the comments in WebModuleDeployer
293          *for a discussion of the root cause of this bug. Use the List of classpath entries set by the
294          *constructor (either by default to preserve the old behavior or via an explicit argument passed from
295          *the method that instantiated EJBCompiler to supply an alternate classpath List).
296          */

297         // converts all the class paths to an array
298
String JavaDoc[] classPathUrls = new String JavaDoc[this.classpathForCompilation.size()];
299         classPathUrls = (String JavaDoc[]) this.classpathForCompilation.toArray(classPathUrls);
300         
301         ejbcContext.setClasspathUrls(classPathUrls);
302
303         // verify ejbc context
304
verifyContext();
305
306         // if redeploy, load the old DDs for redeployment optimization
307
if ( this.ejbcContext.isRedeploy() ) {
308
309             String JavaDoc oldAppRoot = ejbcContext.getOldSrcDir().getCanonicalPath();
310
311             // Form old ejb classpath by taking new ejb classpath and
312
// replacing the renamed repository directory with the original
313
// repository directory. This saves us from having to open
314
// the old .ear just to get the module names. If the module
315
// names have changed, there will just be fewer reused stubs.
316
// this list does not have the stubs dir in it
317
List JavaDoc oldEjbClassPath = new ArrayList JavaDoc();
318             String JavaDoc newStubsDir = ejbcContext.getStubsDir().getCanonicalPath();
319             for(int i = 0; i < classPathUrls.length; i++) {
320                 String JavaDoc nextNew = classPathUrls[i];
321                 if( nextNew.startsWith(appRoot) ) {
322                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc(nextNew);
323                     StringBuffer JavaDoc nextOld = sb.replace(0, appRoot.length(),
324                                                       oldAppRoot);
325                     oldEjbClassPath.add(nextOld.toString());
326                 } else if(!nextNew.equals(newStubsDir)) {
327                     oldEjbClassPath.add(nextNew);
328                 }
329             }
330
331             final ClassLoader JavaDoc oldEjbClassLoader =
332                 DeploymentUtils.getClassLoader(oldEjbClassPath,
333                     request.getParentClassLoader(), this.ejbcContext.getOldStubsDir());
334             this.ejbcContext.setOldClassLoader(oldEjbClassLoader);
335
336         }
337
338         // calls ejbc
339
clientStubs = IASEJBC.ejbc(this.ejbcContext);
340
341         UniqueIdGenerator uidGenerator = UniqueIdGenerator.getInstance();
342         long uid = uidGenerator.getNextUniqueId();
343
344         application.setUniqueId(uid);
345
346         this.appManager.saveAppDescriptor(this.name, application,
347             request.getDeployedDirectory().getCanonicalPath(),
348             request.getGeneratedXMLDirectory().getCanonicalPath(), false);
349
350         return clientStubs;
351     }
352
353     /**
354      * Sets the ejb portion of the class path in the ejbc context.
355      *
356      * @param ejbClassPath list of ejb class path urls for this application
357      */

358     private void setEjbClasspath(List JavaDoc ejbClassPath) {
359
360         String JavaDoc[] ejbClassPathUrls = new String JavaDoc[ejbClassPath.size()];
361         ejbClassPathUrls = (String JavaDoc[]) ejbClassPath.toArray(ejbClassPathUrls);
362         this.ejbcContext.setEjbClasspathUrls(ejbClassPathUrls);
363     }
364
365     /**
366      * EJBC for a stand alone ejb module.
367      *
368      * @return the client stubs as zip entries; these entries are added to
369      * the client jar
370      *
371      * @exception Exception error while running ejbc
372      */

373     private ZipItem[] preDeployModule() throws Exception JavaDoc
374     {
375         ZipItem[] clientStubs = null;
376
377         Application application = request.getDescriptor();
378         ejbcContext.setDescriptor(application);
379
380         /*
381          *Bug 4980750 - See also the comments in WebModuleDeployer
382          *for a discussion of the root cause of this bug. Use the List of classpath entries set by the
383          *constructor (either by default to preserve the old behavior or via an explicit argument passed from
384          *the method that instantiated EJBCompiler to supply an alternate classpath List).
385          */

386         // converts all the class paths to an array
387
String JavaDoc[] classPathUrls = new String JavaDoc[this.classpathForCompilation.size()];
388         classPathUrls = (String JavaDoc[]) this.classpathForCompilation.toArray(classPathUrls);
389         
390         ejbcContext.setClasspathUrls(classPathUrls);
391
392         // verify ejbc context
393
verifyContext();
394
395         // if redeploy, load the old DDs for redeployment optimization
396
if ( this.ejbcContext.isRedeploy() ) {
397
398             String JavaDoc oldModRoot = ejbcContext.getOldSrcDir().getCanonicalPath();
399
400             // module root is the only class path in a std alone module
401
List JavaDoc oldEjbClassPath = new ArrayList JavaDoc();
402             oldEjbClassPath.add(oldModRoot);
403
404             final ClassLoader JavaDoc oldEjbClassLoader =
405                 DeploymentUtils.getClassLoader(oldEjbClassPath,
406                     request.getParentClassLoader(), this.ejbcContext.getOldStubsDir());
407             this.ejbcContext.setOldClassLoader(oldEjbClassLoader);
408
409         }
410
411
412         // calls ejbc
413
clientStubs = IASEJBC.ejbc(this.ejbcContext);
414         
415         
416         
417         UniqueIdGenerator uidGenerator = UniqueIdGenerator.getInstance();
418         long uid = uidGenerator.getNextUniqueId();
419         
420         for (Iterator JavaDoc itr = application.getEjbBundleDescriptors().iterator();
421             itr.hasNext();)
422         {
423             
424             // for stand alone ejb module, there will be
425
// one EjbBundleDescriptor
426
EjbBundleDescriptor bundleDesc = (EjbBundleDescriptor) itr.next();
427             
428             // sets the unique id of all the beans in this bundle
429
bundleDesc.setUniqueId(uid);
430         }
431         this.moduleManager.saveAppDescriptor(this.name, application,
432             request.getDeployedDirectory().getCanonicalPath(),
433             request.getGeneratedXMLDirectory().getCanonicalPath(), true);
434
435         return clientStubs;
436     }
437
438     /**
439      * Throws an exception if required elements of the ejbc context is null.
440      */

441     void verifyContext() throws IASDeploymentException
442     {
443         if ( (this.ejbcContext.getSrcDir() == null)
444                 || (this.ejbcContext.getStubsDir() == null)
445                 || (this.ejbcContext.getDescriptor() == null)
446                 || (this.ejbcContext.getRmicOptions() == null)
447                 || (this.ejbcContext.getJavacOptions() == null)
448                 || (this.ejbcContext.getTiming() == null))
449         {
450             // error - required element is missing
451
String JavaDoc msg = localStrings.getString(
452                 "enterprise.deployment.backend.bad_ejbc_ctx");
453             throw new IASDeploymentException(msg);
454         }
455     }
456
457     ///////////////////////////////////////////////////////////////////////////
458

459     IASDeploymentException wrapException(Throwable JavaDoc t)
460     {
461         String JavaDoc msg = localStrings.getString(
462                         "enterprise.deployment.backend.fatal_ejbc_error" );
463
464         if(t instanceof java.rmi.RemoteException JavaDoc)
465         {
466             msg += localStrings.getString(
467                     "enterprise.deployment.backend.ejbc_remoteexception", t );
468         }
469
470         return new IASDeploymentException(msg, t);
471     }
472
473
474     ///////////////////////////////////////////////////////////////////////////
475

476     private String JavaDoc name;
477     private ModulesManager moduleManager;
478     private AppsManager appManager;
479     private DeploymentRequest request;
480     private EjbcContextImpl ejbcContext;
481     
482     /** Added to support fix for 4980750 so WebModuleDeployer can specify an altered classpath for use during compilation. */
483     private java.util.List JavaDoc classpathForCompilation;
484
485     private static final Logger JavaDoc _logger = DeploymentLogger.get();
486     private static StringManager localStrings =
487             StringManager.getManager( EJBCompiler.class );
488 }
489
Popular Tags