KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > tools > verifier > VerificationHandler


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 package com.sun.enterprise.tools.verifier;
24
25 import java.io.File JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.text.SimpleDateFormat JavaDoc;
29 import java.util.*;
30 import java.util.logging.Level JavaDoc;
31 import java.util.logging.LogRecord JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33
34 import org.xml.sax.SAXParseException JavaDoc;
35 import javax.enterprise.deploy.shared.ModuleType JavaDoc;
36
37 import com.sun.enterprise.deployment.archivist.AppClientArchivist;
38 import com.sun.enterprise.deployment.archivist.ApplicationArchivist;
39 import com.sun.enterprise.deployment.archivist.Archivist;
40 import com.sun.enterprise.deployment.archivist.ArchivistFactory;
41 import com.sun.enterprise.deployment.archivist.ConnectorArchivist;
42 import com.sun.enterprise.deployment.archivist.EjbArchivist;
43 import com.sun.enterprise.deployment.archivist.PluggableArchivistsHelper;
44 import com.sun.enterprise.deployment.archivist.WebArchivist;
45 import com.sun.enterprise.deployment.backend.J2EEModuleExploder;
46 import com.sun.enterprise.deployment.backend.OptionalPkgDependency;
47 import com.sun.enterprise.deployment.deploy.shared.AbstractArchive;
48 import com.sun.enterprise.deployment.deploy.shared.FileArchiveFactory;
49 import com.sun.enterprise.deployment.util.ApplicationValidator;
50 import com.sun.enterprise.deployment.*;
51 import com.sun.enterprise.logging.LogDomains;
52 import com.sun.enterprise.tools.verifier.apiscan.stdapis.APIRepository;
53 import com.sun.enterprise.tools.verifier.app.ApplicationVerifier;
54 import com.sun.enterprise.tools.verifier.appclient.AppClientVerifier;
55 import com.sun.enterprise.tools.verifier.connector.ConnectorVerifier;
56 import com.sun.enterprise.tools.verifier.ejb.EjbVerifier;
57 import com.sun.enterprise.tools.verifier.web.WebVerifier;
58 import com.sun.enterprise.util.io.FileUtils;
59 import com.sun.enterprise.util.LocalStringManagerImpl;
60 import com.sun.enterprise.util.FileUtil;
61 import com.sun.enterprise.util.JarClassLoader;
62 import com.sun.enterprise.loader.EJBClassPathUtils;
63 import com.sun.enterprise.server.PELaunch;
64
65
66 /**
67  * It is responsible for creating the application descriptor,
68  * exploding the archive, creating the application classloader,
69  * and invoking the appropriate check managers that load and run
70  * the verifier tests.
71  *
72  * @author Vikas Awasthi
73  */

74 public class VerificationHandler {
75
76     private final String JavaDoc TMPDIR = System.getProperty("java.io.tmpdir");
77     private SimpleDateFormat JavaDoc dateFormatter = new SimpleDateFormat JavaDoc(
78             "yyyyMMddhhmmss"); // NOI18N
79
private String JavaDoc explodeDir = TMPDIR + File.separator + "exploded" + // NOI18N
80
dateFormatter.format(new Date());
81     private LocalStringManagerImpl smh = StringManagerHelper.getLocalStringsManager();
82     private FrameworkContext frameworkContext = null;
83     private Logger JavaDoc logger = LogDomains.getLogger(
84             LogDomains.AVK_VERIFIER_LOGGER);
85     private Application application = null;
86     private ResultManager resultManager = null;
87     private Archivist archivist = null;
88     private boolean isBackend = false;
89     private List<String JavaDoc> classPath = null;
90     private final int MAX_WINDOWS_PATH_LIMIT = 248;
91
92     public VerificationHandler(FrameworkContext frameworkContext)
93             throws IOException JavaDoc {
94         this.frameworkContext = frameworkContext;
95         try {
96             initStandalone();
97         } catch(IOException JavaDoc ioe) {
98             cleanup();
99             throw ioe;
100         } catch(RuntimeException JavaDoc re) {
101             cleanup();
102             throw re;
103         }
104     }
105
106     public VerificationHandler(FrameworkContext frameworkContext,
107                                Application application,
108                                AbstractArchive abstractArchive,
109                                List<String JavaDoc> classPath) {
110         this.frameworkContext = frameworkContext;
111         init();
112         this.application = application;
113         this.frameworkContext.setClassPath(classPath);
114         this.frameworkContext.setJarFileName(application.getRegistrationName());
115         isBackend = true;
116         this.frameworkContext.setApplication(application);
117         this.frameworkContext.setAbstractArchive(abstractArchive);
118     }
119
120     public ResultManager verifyArchive() { // should we throw exception here
121
if(!application.isVirtual()) { // don't run app tests for standalone module
122
runVerifier(new ApplicationVerifier(frameworkContext, application));
123         }
124
125         for (Iterator itr = application.getEjbBundleDescriptors().iterator();
126              itr.hasNext();) {
127             EjbBundleDescriptor ejbd = (EjbBundleDescriptor) itr.next();
128             runVerifier(new EjbVerifier(frameworkContext, ejbd));
129         }
130
131         for (Iterator itr = application.getWebBundleDescriptors().iterator();
132              itr.hasNext();) {
133             WebBundleDescriptor webd = (WebBundleDescriptor) itr.next();
134             runVerifier(new WebVerifier(frameworkContext, webd));
135         }
136
137         for (Iterator itr = application.getApplicationClientDescriptors()
138                 .iterator();
139              itr.hasNext();) {
140             ApplicationClientDescriptor appClientDescriptor =
141                                     (ApplicationClientDescriptor) itr.next();
142             runVerifier(new AppClientVerifier(frameworkContext,appClientDescriptor));
143         }
144
145         for (Iterator itr = application.getRarDescriptors().iterator();
146              itr.hasNext();) {
147             ConnectorDescriptor cond = (ConnectorDescriptor) itr.next();
148             runVerifier(new ConnectorVerifier(frameworkContext, cond));
149         }
150         
151         return resultManager;
152     }
153     /**
154      * common initialization method for the call from backend and standalone
155      * invocation.
156      */

157     private void init() {
158         frameworkContext.setResultManager(resultManager = new ResultManager());
159         try {
160             APIRepository.Initialize(
161                     frameworkContext.getConfigDirStr() + File.separator +
162                     "standard-apis.xml"); // NOI18N
163
} catch (Exception JavaDoc e) {
164             throw new RuntimeException JavaDoc(e);
165         }
166     }
167     /**
168      * initialization done for standalone verifier invocation.
169      * @throws IOException
170      */

171     private void initStandalone() throws IOException JavaDoc {
172         init();
173         logger.log(Level.FINE, getClass().getName() + ".debug.startingLoadJar");
174         if (!frameworkContext.isPortabilityMode()) {
175             String JavaDoc as_config_dir =
176                     System.getProperty("com.sun.aas.installRoot")+File.separator+"config";
177             classPath = PELaunch.getServerClassPath(as_config_dir,
178                                                     frameworkContext.getDomainDir());
179         }
180
181         // initialize /tmp/* directories
182
initVerifierTmpDirs();
183         String JavaDoc jarFile = frameworkContext.getJarFileName();
184         //We must call OptionalPkgDependency.satisfyOptionalPackageDependencies() before explodeArchive,
185
//because inside this call, the list of installed optional packages in the system gets initialised.
186
//That list is then used inside optionalPackageDependencyLogic() code.
187
//It looks to be a bug as ideally this kind of dependency should be taken care of inside
188
//OptionalPkgDependency class itself.
189
//But any way, we don't have a choice but to make this work around in our code.
190
OptionalPkgDependency.satisfyOptionalPackageDependencies();
191         archivist = ArchivistFactory.getArchivistForArchive(new File JavaDoc(jarFile));
192         if(archivist == null) {
193             throw new RuntimeException JavaDoc(
194                     smh.getLocalString(getClass().getName() + ".notAJavaEEArchive", // NOI18N
195
"[ {0} ] is not a valid Java EE archive", // NOI18N
196
new Object JavaDoc[]{jarFile}));
197         }
198         explodeArchive(new File JavaDoc(jarFile));
199         checkAndExplodeArchiveInWindowsPlatform(jarFile);
200         Descriptor.setBoundsChecking(false);
201
202         try {
203             createApplicationDescriptor();
204         } catch (IOException JavaDoc e) {
205             log("Problem in creating application descriptor", e);
206             throw e;
207         } catch (SAXParseException JavaDoc se) {
208             log("Problem in parsing the xml file. For " +
209                     se.getLocalizedMessage() +
210                     ", error at line " +
211                     se.getLineNumber() +
212                     ", column " +
213                     se.getColumnNumber(), se);
214             IOException JavaDoc ioe = new IOException JavaDoc();
215             ioe.initCause(se);
216             throw ioe;
217         }
218         ((Descriptor) application).visit(new ApplicationValidator());
219     }
220
221     private void runVerifier(BaseVerifier baseVerifier) {
222         try {
223             baseVerifier.verify();
224         } catch (Exception JavaDoc e) {
225             log("Problem in running tests for :" +
226                     baseVerifier.getDescriptor().getName(),
227                     e);
228         }
229     }
230
231     private void createApplicationDescriptor() throws IOException JavaDoc,
232             SAXParseException JavaDoc {
233 // the code below is used by the deploytool GUI.
234
PluggableArchivistsHelper defaultArchivists = new PluggableArchivistsHelper();
235         defaultArchivists.registerArchivist(new ApplicationArchivist());
236         defaultArchivists.registerArchivist(new WebArchivist());
237         defaultArchivists.registerArchivist(new EjbArchivist());
238         defaultArchivists.registerArchivist(new ConnectorArchivist());
239         defaultArchivists.registerArchivist(new AppClientArchivist());
240         AbstractArchive abstractArchive =
241                 new FileArchiveFactory().openArchive(
242                         frameworkContext.getExplodedArchivePath());
243         frameworkContext.setAbstractArchive(abstractArchive);
244         archivist.setPluggableArchivists(defaultArchivists);
245         archivist.setXMLValidationLevel("full");
246         archivist.setRuntimeXMLValidation(true);
247         archivist.setRuntimeXMLValidationLevel("full");
248         archivist.setAnnotationProcessingRequested(true);
249         archivist.setAnnotationErrorHandler(new VerifierErrorHandler(resultManager));
250
251         String JavaDoc jarName = new File JavaDoc(abstractArchive.getArchiveUri()).getName();
252         createApplicationDescriptor0(abstractArchive, jarName);
253     }
254
255     private void explodeArchive(File JavaDoc archiveFile) throws IOException JavaDoc {
256         if (archiveFile.isDirectory()) {
257             frameworkContext.setExplodedArchivePath(
258                     archiveFile.getAbsolutePath());
259             return;
260         }
261
262         String JavaDoc appName = FileUtils.makeFriendlyFileNameNoExtension(
263                 archiveFile.getName());
264         File JavaDoc appDir = new File JavaDoc(new File JavaDoc(explodeDir), appName);
265         frameworkContext.setExplodedArchivePath(appDir.getAbsolutePath());
266
267         try {
268             ModuleType JavaDoc moduleType = archivist.getModuleType();
269             if(ModuleType.EAR.equals(moduleType)) { // EAR file
270
// Explode the archive and create a descriptor. This is
271
// not complete at this point. It will be filled with all info later.
272
application = J2EEModuleExploder.explodeEar(archiveFile, appDir);
273             } else if ( ModuleType.EJB.equals(moduleType) ||
274                     ModuleType.CAR.equals(moduleType) ||
275                     ModuleType.RAR.equals(moduleType) ||
276                     ModuleType.WAR.equals(moduleType) ) {
277                 J2EEModuleExploder.explodeJar(archiveFile, appDir);
278             } else
279                 throw new FileNotFoundException JavaDoc(
280                         "Deployment descriptor not found in " +
281                         archiveFile.getName());
282         } catch (Exception JavaDoc e) {
283             IOException JavaDoc ioe = new IOException JavaDoc(e.getMessage());
284             ioe.initCause(e);
285             throw ioe;
286         }
287     }
288
289     // See issue: 6329054. In windows max allowed path length is 248. Check
290
// if this length is exceeded during archive explosion. If the length
291
// exceeds the max limit then use %HOMEDRIVE%/temp as the temp directory
292
// for exploding the archive. This is done because default temp directory
293
// itself consumes a lot of path length. If if file length still exceeds
294
// max limit or if %HOMEDRIVE%/temp does not exist then throw exception
295
// giving proper message to the user.
296
private void checkAndExplodeArchiveInWindowsPlatform(String JavaDoc jarFile)
297             throws IOException JavaDoc {
298         if(!System.getProperty("os.name").toLowerCase().startsWith("win"))
299             return;
300         
301         if(!testFileLength(new File JavaDoc(explodeDir))) {
302             File JavaDoc tempDir = new File JavaDoc(System.getProperty("home.drive"),"temp");
303             if(!tempDir.exists())
304                 throw new IOException JavaDoc(smh.getLocalString
305                         (getClass().getName() + ".exception1","Maximum Path " +
306                         "Length exceeded. The application uses long file names " +
307                         "which has exceeded maximum allowed path length in windows." +
308                         " Please shorten the file names and then continue. Not " +
309                         "able to proceed further as [{0}] does not exist",
310                         new Object JavaDoc[]{tempDir.getAbsolutePath()}));
311             if(!FileUtil.deleteDir(new File JavaDoc(explodeDir))) {
312                 logger.log(Level.WARNING,
313                             getClass().getName() + ".explodedirdeleteerror", // NOI18N
314
new Object JavaDoc[] {explodeDir});
315             }
316             explodeDir = tempDir.getAbsolutePath() + File.separator + "exploded" +
317                     dateFormatter.format(new Date());
318             explodeArchive(new File JavaDoc(jarFile));
319             if(!testFileLength(new File JavaDoc(explodeDir)))
320                 throw new IOException JavaDoc(smh.getLocalString
321                         (getClass().getName() + ".exception","Maximum Path Length " +
322                         "exceeded. The application uses long file names which has " +
323                         "exceeded maximum allowed path length in windows. Please " +
324                         "shorten the file names and then continue."));
325         }
326     }
327     
328     /** Maximum allowed path length in windows is 248. Return false if any
329      * exploded file exceeds this length. */

330     private boolean testFileLength(File JavaDoc file) throws IOException JavaDoc {
331         if(file.getAbsolutePath().length() > MAX_WINDOWS_PATH_LIMIT) {
332             logger.log(Level.WARNING,
333                         getClass().getName() + ".maxlength.exceeded", // NOI18N
334
new Object JavaDoc[] {file.getAbsolutePath(),
335                                       file.getAbsolutePath().length(),
336                                       MAX_WINDOWS_PATH_LIMIT});
337             return false;
338         } else if(file.getCanonicalPath().length() > MAX_WINDOWS_PATH_LIMIT) {
339             // absolute paths may have ~1. Since windows behave strangely
340
// both absolute path and canonical path are used
341
logger.log(Level.WARNING,
342                         getClass().getName() + ".maxlength.exceeded", // NOI18N
343
new Object JavaDoc[] {file.getCanonicalPath(),
344                                       file.getCanonicalPath().length(),
345                                       MAX_WINDOWS_PATH_LIMIT});
346             return false;
347         }
348         
349         if(!file.isDirectory())
350             return true;
351         
352         for (File JavaDoc file1 : file.listFiles())
353             if(!testFileLength(file1))
354                 return false;
355         return true;
356     }
357
358     private boolean initVerifierTmpDirs() throws IOException JavaDoc {
359         // Make sure we can create the directory appservResultDir
360
File JavaDoc test = new File JavaDoc(explodeDir);
361         if (!test.isDirectory() && !test.getAbsoluteFile().mkdirs()) {
362             logger.log(Level.SEVERE, getClass().getName() +
363                     ".explodedircreateerror", test.getAbsolutePath()); // NOI18N
364
throw new IOException JavaDoc(smh.getLocalString(getClass().getName()
365                     + ".explodedircreateerror", test.getAbsolutePath())); // NOI18N
366
}
367         return true;
368     }
369
370     public void cleanup() {
371         if(!isBackend && application!=null)
372             ((JarClassLoader)application.getClassLoader()).done();
373         if(!isBackend &&
374             !((new File JavaDoc(frameworkContext.getJarFileName())).isDirectory()))
375             FileUtil.deleteDir(new File JavaDoc(explodeDir));
376     }
377
378     /**
379      * This method is used to log exception messges in the error vector of
380      * ResultManager object.
381      * @param message
382      * @param e
383      */

384     private void log(String JavaDoc message, Exception JavaDoc e) {
385         if (message == null) message = "";
386         LogRecord JavaDoc logRecord = new LogRecord JavaDoc(Level.SEVERE, message);
387         logRecord.setThrown(e);
388         frameworkContext.getResultManager().log(logRecord);
389     }
390
391     private ClassLoader JavaDoc getEarClassLoader(Application dummyApp) throws IOException JavaDoc {
392         List<String JavaDoc> classPath = EJBClassPathUtils.getApplicationClassPath(dummyApp,
393                                         frameworkContext.getExplodedArchivePath());
394         return createClassLoaderFromPath(classPath);
395     }
396
397     private ClassLoader JavaDoc getModuleClassLoader(ModuleType JavaDoc type) throws IOException JavaDoc {
398         String JavaDoc moduleRoot = frameworkContext.getExplodedArchivePath();
399         List<String JavaDoc> classPath = EJBClassPathUtils.getModuleClassPath(type, moduleRoot, moduleRoot);
400         return createClassLoaderFromPath(classPath);
401     }
402     
403     private ClassLoader JavaDoc createClassLoaderFromPath(List<String JavaDoc> classPath) throws IOException JavaDoc {
404         if(!frameworkContext.isPortabilityMode()) {
405             classPath.addAll(0, this.classPath);
406             frameworkContext.setClassPath(classPath);
407         } else {
408             String JavaDoc as_lib_root = System.getProperty("com.sun.aas.installRoot")+
409                                                     File.separator+
410                                                     "lib"+ // NOI18N
411
File.separator;
412             classPath.add(as_lib_root + "javaee.jar"); // NOI18N
413
}
414
415         JarClassLoader jcl = new JarClassLoader();
416         // toURI().toURL() takes care of all the escape characters in the
417
// absolutePath. The toURI() method encodes all escape characters. Since
418
// EJBClassLoader does not decode these urls here only toURL() is used.
419
// Once this issue is fixed in EJBClassloader we can change it to
420
// toURI().toURL()
421
for (String JavaDoc path : classPath)
422             jcl.appendURL(new File JavaDoc(path));
423         return jcl;
424     }
425
426     /**
427      * This method populates the missing information in Application object
428      * that is already created in {@link #explodeArchive(java.io.File)}.
429      * @param abstractArchive
430      * @param jarName
431      * @throws IOException
432      * @throws SAXParseException
433      */

434     private void createApplicationDescriptor0(AbstractArchive abstractArchive,
435                                               String JavaDoc jarName) throws IOException JavaDoc, SAXParseException JavaDoc{
436         if (archivist.getModuleType()==ModuleType.EAR) {
437                 ClassLoader JavaDoc classLoader = getEarClassLoader(application);
438                 application.setClassLoader(classLoader);
439                 archivist.setClassLoader(classLoader);
440                 archivist.setHandleRuntimeInfo(!frameworkContext.isPortabilityMode());
441                 archivist.readPersistenceDeploymentDescriptors(abstractArchive, application);
442                 ((ApplicationArchivist) archivist).readModulesDescriptors(application, abstractArchive);
443                 if(!frameworkContext.isPortabilityMode()) {
444                     // this recurssively reads runtime DD for all the modules.
445
archivist.readRuntimeDeploymentDescriptor(abstractArchive, application);
446                 }
447                 application.setRegistrationName(jarName);
448         } else {
449             ClassLoader JavaDoc classLoader = getModuleClassLoader(archivist.getModuleType());
450             archivist.setClassLoader(classLoader);
451             application = ApplicationArchivist.openArchive(jarName,
452                                                     archivist,
453                                                     abstractArchive,
454                                                     !frameworkContext.isPortabilityMode());
455             application.setClassLoader(classLoader);
456         }
457     }
458 }
459
Popular Tags