KickJava   Java API By Example, From Geeks To Geeks.

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


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 package com.sun.enterprise.deployment.backend;
25
26 import java.io.IOException JavaDoc;
27 import java.io.*;
28 import java.util.*;
29 import java.util.jar.*;
30 import java.nio.*;
31 import java.nio.channels.*;
32
33 import com.sun.enterprise.config.ConfigContext;
34 import com.sun.enterprise.config.ConfigException;
35 import com.sun.enterprise.config.serverbeans.DasConfig;
36 import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
37 import com.sun.enterprise.deployment.Application;
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.deploy.shared.AbstractArchive;
42 import com.sun.enterprise.deployment.deploy.shared.AbstractArchiveFactory;
43 import com.sun.enterprise.deployment.deploy.shared.FileArchive;
44 import com.sun.enterprise.deployment.deploy.shared.FileArchiveFactory;
45 import com.sun.enterprise.deployment.deploy.shared.InputJarArchive;
46 import com.sun.enterprise.deployment.deploy.shared.JarArchiveFactory;
47 import com.sun.enterprise.deployment.io.DeploymentDescriptorFile;
48 import com.sun.enterprise.deployment.util.ModuleDescriptor;
49 import com.sun.enterprise.server.ApplicationServer;
50 import com.sun.enterprise.util.i18n.StringManager;
51 import com.sun.enterprise.util.io.FileUtils;
52 import com.sun.enterprise.util.OS;
53 import com.sun.enterprise.util.zip.ZipFile;
54 import com.sun.enterprise.util.zip.ZipFileException;
55
56 import java.io.File JavaDoc;
57 import java.io.IOException JavaDoc;
58 import java.util.*;
59 import java.util.logging.Level JavaDoc;
60 import java.util.logging.Logger JavaDoc;
61 import java.util.zip.ZipException JavaDoc;
62 import javax.enterprise.deploy.shared.ModuleType JavaDoc;
63
64
65 /**
66  * this class is responsible for exploding a J2EE archive file into
67  * a directory/file based structures that is used by the deployment
68  * and app server runtime.
69  *
70  * @author Jerome Dochez
71  */

72
73 public class J2EEModuleExploder {
74     
75     private static StringManager localStrings =
76             StringManager.getManager( J2EEModuleExploder.class );
77
78     private static Logger JavaDoc logger = null;
79     
80     private static final String JavaDoc PRESERVED_MANIFEST_NAME = java.util.jar.JarFile.MANIFEST_NAME + ".preserved";
81     
82     private static final String JavaDoc WEB_INF_PREFIX = "WEB-INF/";
83
84     private static String JavaDoc validationLevel = null;
85     
86     /**
87      * explode the passed archive file inside the directory
88      * <p>
89      * This is the original signature for this method. It now delegates to the other variant
90      * but specifies the directory argument as also the directory into which to expand nested jar
91      * file contents. This preserves the original behavior of the method.
92      *
93      * @param the archive
94      * @param the destination directory
95      * @param the module name for the archive
96      */

97     public static void explode(File archive, File directory, String JavaDoc moduleName)
98     throws IOException JavaDoc, IASDeploymentException {
99         explode(archive, directory, moduleName, false);
100     }
101     
102     /**
103      * explode the passed archive file inside the directory
104      * @param the archive
105      * @param the destination directory
106      * @param the module name for the archive
107      * @param whether to prevent manifests from exploded nested jar files from overwriting the archive's manifest
108      */

109     public static void explode(File archive, File directory, String JavaDoc moduleName, boolean preserveManifest)
110     throws IOException JavaDoc, IASDeploymentException {
111         assert archive != null;
112         
113         
114         AbstractArchiveFactory factory = null;
115         if (archive.isDirectory()) {
116             factory = new FileArchiveFactory();
117         } else {
118             factory = new JarArchiveFactory();
119         }
120         AbstractArchive source = factory.openArchive(archive.getAbsolutePath());
121         
122         // now copy the archive, let the archivist do the job...
123
Archivist archivist = null;
124         try {
125             archivist = ArchivistFactory.getArchivistForArchive(source);
126             if (archivist == null) {
127                 String JavaDoc msg = localStrings.getString
128                         ("enterprise.deployment.backend.no_archivist_recognized_arch",
129                         archive.getAbsolutePath()
130                         );
131                 throw new IASDeploymentException(msg);
132             }
133         } catch (IOException JavaDoc ioe) {
134             String JavaDoc msg = localStrings.getString
135                     ("enterprise.deployment.backend.error_getting_archivist",
136                     archive.getAbsolutePath()
137                     );
138             throw new IASDeploymentException(msg, ioe);
139         }
140         if (!archivist.getModuleType().equals(ModuleType.EAR)) {
141             explodeModule(archivist, source, directory, moduleName, preserveManifest);
142         }
143     }
144     
145     private static void explodeModule(Archivist archivist, AbstractArchive source, File directory, String JavaDoc moduleName, boolean preserveManifest)
146     throws IOException JavaDoc, IASDeploymentException {
147         
148         File explodedManifest = null;
149         File preservedManifestFromArchive = null;
150         
151         FileArchive target = new FileArchive();
152         target.create(directory.getAbsolutePath());
153         
154         explodeJar(new File(source.getArchiveUri()), directory);
155         //archivist.copyInto(source, target);
156

157         if (preserveManifest) {
158             explodedManifest = new File(directory, java.util.jar.JarFile.MANIFEST_NAME);
159             if (explodedManifest.exists()) {
160                 /* Rename the manifest so it can be restored later. */
161                 preservedManifestFromArchive = new File(directory, PRESERVED_MANIFEST_NAME);
162                 try {
163                     if (OS.isWindows()) {
164                         FileUtils.validateWindowsFilePathLength(preservedManifestFromArchive);
165                     }
166                 } catch (IOException JavaDoc ioe) {
167                     IOException JavaDoc newIOE = new IOException JavaDoc(localStrings.getString(
168                             "enterprise.deployment.backend.error_saving_manifest",
169                             new Object JavaDoc[]
170                                 { explodedManifest.getAbsolutePath(),
171                                           preservedManifestFromArchive.getAbsolutePath()
172                                 }
173                             ));
174                     newIOE.initCause(ioe);
175                     throw newIOE;
176                 }
177                 if ( ! explodedManifest.renameTo(preservedManifestFromArchive)) {
178                     throw new RuntimeException JavaDoc(localStrings.getString(
179                             "enterprise.deployment.backend.error_saving_manifest",
180                             new Object JavaDoc[]
181                     { explodedManifest.getAbsolutePath(),
182                               preservedManifestFromArchive.getAbsolutePath()
183                     } ) ) ;
184                 }
185             }
186         }
187         // now explode all top level jar files and delete them.
188
// this cannot be done before since the optionalPkgDependency
189
// require access to the manifest file of each .jar file.
190
for (Enumeration itr = source.entries();itr.hasMoreElements();) {
191             String JavaDoc fileName = (String JavaDoc) itr.nextElement();
192             
193             
194             // check for optional packages depencies
195
// XXX : JEROME look if this is still done
196
// optionalPkgDependencyLogic(new File(directory, fileName));
197

198              /*
199               *Expand the file only if it is a jar and only if it does not lie in WEB-INF/lib.
200               */

201             if (fileName.toLowerCase().endsWith(".jar") && ( ! fileName.replace('\\', '/').toUpperCase().startsWith(WEB_INF_PREFIX)) ) {
202                 
203                 try {
204                     File f = new File(directory, fileName);
205                     
206                     File targetDirectory = directory;
207                     
208                     ZipFile zip = new ZipFile(f, targetDirectory);
209                     zip.explode();
210                 } catch(ZipFileException e) {
211                     IOException JavaDoc ioe = new IOException JavaDoc(e.getMessage());
212                     ioe.initCause(e);
213                     throw ioe;
214                 }
215             }
216         }
217          /*
218           *If the archive's manifest was renamed to protect it from being overwritten by manifests from
219           *jar files, then rename it back. Delete an existing manifest file first if needed.
220           */

221         if (preservedManifestFromArchive != null) {
222             if (explodedManifest.exists()) {
223                 if ( ! explodedManifest.delete()) {
224                     throw new RuntimeException JavaDoc(localStrings.getString(
225                             "enterprise.deployment.backend.error_deleting_manifest",
226                             new Object JavaDoc []
227                     { explodedManifest.getAbsolutePath(),
228                               preservedManifestFromArchive.getAbsolutePath()
229                     }
230                     ) );
231                 }
232             }
233             
234             if ( ! preservedManifestFromArchive.renameTo(explodedManifest)) {
235                 throw new RuntimeException JavaDoc(localStrings.getString(
236                         "enterprise.deployment.backend.error_restoring_manifest",
237                         new Object JavaDoc []
238                 { preservedManifestFromArchive.getAbsolutePath(),
239                           explodedManifest.getAbsolutePath()
240                 }
241                 ) );
242             }
243         }
244         
245         source.close();
246         target.close();
247     }
248
249     public static Application explodeEar(File source, File destination) throws Exception JavaDoc {
250         
251         // first explode the ear file
252
explodeJar(source, destination);
253         
254         // now we need to load the application standard deployment descriptor.
255
ApplicationArchivist archivist = new ApplicationArchivist();
256         archivist.setXMLValidationLevel(getValidationLevel());
257         FileArchive appArchive = new FileArchive();
258         appArchive.open(destination.getAbsolutePath());
259         
260         archivist.setManifest(appArchive.getManifest());
261         
262         // read the standard deployment descriptors
263
Application appDesc = null;
264         if (archivist.hasStandardDeploymentDescriptor(appArchive)) {
265             appDesc = (Application)
266             archivist.readStandardDeploymentDescriptor(appArchive);
267         } else {
268             appDesc = Application.createApplication(appArchive,true);
269         }
270
271         archivist.setDescriptor(appDesc);
272         
273         // ok we should now have the list of modules, so we can happily explode them...
274
Iterator<ModuleDescriptor> bundles = appDesc.getModules();
275         while (bundles.hasNext()) {
276             
277             ModuleDescriptor bundle = bundles.next();
278             
279             String JavaDoc moduleName = bundle.getArchiveUri();
280             String JavaDoc massagedModuleName = FileUtils.makeFriendlyFilename(moduleName);
281             File archiveFile = new File(destination, moduleName);
282             File moduleDir = new File(destination, massagedModuleName);
283             explodeJar(archiveFile, moduleDir);
284             
285             // delete the original module file
286
archiveFile.delete();
287         }
288         
289         return appDesc;
290     }
291     
292     
293     
294     public static void explodeJar(File source, File destination) throws IOException JavaDoc {
295         JarFile jarFile = null;
296         String JavaDoc fileSystemName = null; // declared outside the try block so it's available in the catch block
297
try {
298             jarFile = new JarFile(source);
299             Enumeration<JarEntry> e = jarFile.entries();
300             while (e.hasMoreElements()) {
301                 JarEntry entry = e.nextElement();
302                 fileSystemName = entry.getName().replace('/', File.separatorChar);
303                 File out = new File(destination, fileSystemName);
304                 if (OS.isWindows() ) {
305                     FileUtils.validateWindowsFilePathLength(out);
306                 }
307                 
308                 if (entry.isDirectory()) {
309                     out.mkdirs();
310                 } else {
311                     InputStream is = null;
312                     FileOutputStream fos = null;
313                     try {
314                         if (!out.getParentFile().exists()) {
315                             out.getParentFile().mkdirs();
316                         }
317                         is = new BufferedInputStream(jarFile.getInputStream(entry));
318                         fos = new FileOutputStream(out);
319                         ReadableByteChannel inChannel = Channels.newChannel(is);
320                         FileChannel outChannel = fos.getChannel();
321                         outChannel.transferFrom(inChannel, 0, entry.getSize());
322                     } finally {
323                         if (is!=null)
324                             is.close();
325                         if (fos!=null)
326                             fos.close();
327                     }
328                 }
329             }
330         } catch(Throwable JavaDoc e) {
331             /*
332              *Use the logger here, even though we rethrow the exception. In
333              *at least some cases the caller does not propagate this exception
334              *further, instead replacing it with a serializable
335              *IASDeployException. The added information is then lost.
336              *By logging the exception here, we make sure the log file at least
337              *displays as much as we know about the problem even though the
338              *exception sent to the client may not.
339              */

340             String JavaDoc msg0 = localStrings.getString(
341                     "enterprise.deployment.backend.error_expanding",
342                     new Object JavaDoc[] {source.getAbsolutePath()});
343             String JavaDoc msg = localStrings.getString(
344                     "enterprise.deployment.backend.could_not_expand",
345                     new Object JavaDoc[] {fileSystemName, destination.getAbsolutePath() });
346             IOException JavaDoc ioe = new IOException JavaDoc(msg0);
347             ioe.initCause(e);
348             getLogger().log(Level.SEVERE, msg, ioe);
349             throw ioe;
350         } finally {
351             if (jarFile != null) {
352                 jarFile.close();
353             }
354         }
355     }
356     
357     /**
358      *Retrieves the deployment-related logger for the exploder's private use.
359      *@return Logger for deployment-related messages
360      */

361     private static Logger JavaDoc getLogger() {
362         if (logger == null) {
363             logger = DeploymentLogger.get();
364         }
365         return logger;
366     }
367
368     /**
369      * @return the validation level
370      */

371     private static String JavaDoc getValidationLevel() {
372         if (validationLevel == null) {
373             try {
374                 if (ApplicationServer.getServerContext() == null) {//verifier
375
validationLevel = DeploymentDescriptorFile.FULL_VALIDATION;
376                 } else {
377                     ConfigContext ctx =
378                     ApplicationServer.getServerContext().getConfigContext();
379                     DasConfig dc = ServerBeansFactory.getDasConfigBean(ctx);
380                     validationLevel = dc.getDeployXmlValidation();
381                 }
382             } catch(ConfigException ce) {
383                 //ignore error, provide default
384
validationLevel = DeploymentDescriptorFile.FULL_VALIDATION;
385             }
386         }
387         return validationLevel;
388     }
389 }
390
Popular Tags