KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > deploy > ExpandDeployController


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.deploy;
31
32 import com.caucho.config.types.FileSetType;
33 import com.caucho.loader.DynamicClassLoader;
34 import com.caucho.loader.Environment;
35 import com.caucho.util.L10N;
36 import com.caucho.util.Log;
37 import com.caucho.vfs.Depend;
38 import com.caucho.vfs.Path;
39 import com.caucho.vfs.ReadStream;
40 import com.caucho.vfs.Vfs;
41 import com.caucho.vfs.WriteStream;
42
43 import java.io.IOException JavaDoc;
44 import java.util.jar.Attributes JavaDoc;
45 import java.util.jar.Manifest JavaDoc;
46 import java.util.logging.Level JavaDoc;
47 import java.util.logging.Logger JavaDoc;
48 import java.util.zip.ZipEntry JavaDoc;
49 import java.util.zip.ZipInputStream JavaDoc;
50
51 /**
52  * A deployment entry that expands from an archive (Jar/Zip) file.
53  */

54 abstract public class ExpandDeployController<I extends DeployInstance>
55   extends DeployController<I> {
56   private static final L10N L = new L10N(ExpandDeployController.class);
57   private static final Logger JavaDoc log = Log.open(ExpandDeployController.class);
58
59   private Object JavaDoc _archiveExpandLock = new Object JavaDoc();
60
61   private Path _rootDirectory;
62   private Path _archivePath;
63
64   private FileSetType _expandCleanupFileSet;
65
66   // classloader for the manifest entries
67
private DynamicClassLoader _manifestLoader;
68   private Manifest JavaDoc _manifest;
69
70   protected ExpandDeployController(String JavaDoc id)
71   {
72     this(id, null, null);
73   }
74
75   protected ExpandDeployController(String JavaDoc id,
76                    ClassLoader JavaDoc loader,
77                    Path rootDirectory)
78   {
79     super(id, loader);
80
81     if (rootDirectory == null)
82       rootDirectory = Vfs.getPwd(getParentClassLoader());
83
84     _rootDirectory = rootDirectory;
85   }
86   
87   /**
88    * Gets the root directory
89    */

90   public Path getRootDirectory()
91   {
92     return _rootDirectory;
93   }
94   
95   /**
96    * Sets the root directory
97    */

98   protected void setRootDirectory(Path rootDirectory)
99   {
100     _rootDirectory = rootDirectory;
101   }
102
103   /**
104    * Gets the archive path.
105    */

106   public Path getArchivePath()
107   {
108     return _archivePath;
109   }
110
111   /**
112    * Sets the archive path.
113    */

114   public void setArchivePath(Path path)
115   {
116     _archivePath = path;
117   }
118
119   /**
120    * Returns the manifest.
121    */

122   public Manifest JavaDoc getManifest()
123   {
124     return _manifest;
125   }
126
127   /**
128    * Sets the manifest class loader.
129    */

130   public void setManifestClassLoader(DynamicClassLoader loader)
131   {
132     _manifestLoader = loader;
133   }
134
135   /**
136    * Sets the archive auto-remove file set.
137    */

138   public void setExpandCleanupFileSet(FileSetType fileSet)
139   {
140     _expandCleanupFileSet = fileSet;
141   }
142
143   /**
144    * Merges with the old controller.
145    */

146   @Override JavaDoc
147   protected void mergeController(DeployController oldControllerV)
148   {
149     super.mergeController(oldControllerV);
150
151     ExpandDeployController<I> oldController;
152     oldController = (ExpandDeployController<I>) oldControllerV;
153     
154     if (oldController._expandCleanupFileSet != null)
155       _expandCleanupFileSet = oldController._expandCleanupFileSet;
156   }
157
158   /**
159    * Expand an archive file. The _archiveExpandLock must be obtained
160    * before the expansion.
161    */

162   protected void expandArchive()
163     throws IOException JavaDoc
164   {
165     synchronized (_archiveExpandLock) {
166       if (! expandArchiveImpl()) {
167     try {
168       Thread.sleep(2000);
169     } catch (InterruptedException JavaDoc e) {
170     }
171     
172     expandArchiveImpl();
173       }
174
175       Path path = getRootDirectory().lookup("META-INF/MANIFEST.MF");
176       if (path.canRead()) {
177     ReadStream is = path.openRead();
178     try {
179       _manifest = new Manifest JavaDoc(is);
180     } catch (IOException JavaDoc e) {
181       log.warning(L.l("Manifest file cannot be read for '{0}'.\n{1}",
182               getRootDirectory(), e));
183
184       log.log(Level.FINE, e.toString(), e);
185     } finally {
186       is.close();
187     }
188       }
189     }
190   }
191
192   /**
193    * Adds any class path from the manifest.
194    */

195   protected void addManifestClassPath()
196     throws IOException JavaDoc
197   {
198     DynamicClassLoader loader = Environment.getDynamicClassLoader();
199     if (loader == null)
200       return;
201     
202     Manifest JavaDoc manifest = getManifest();
203
204     if (manifest == null)
205       return;
206
207     Attributes JavaDoc main = manifest.getMainAttributes();
208
209     if (main == null)
210       return;
211     
212     String JavaDoc classPath = main.getValue("Class-Path");
213
214     Path pwd = null;
215
216     if (getArchivePath() != null)
217       pwd = getArchivePath().getParent();
218     else
219       pwd = getRootDirectory();
220
221     if (classPath == null) {
222     }
223     else if (_manifestLoader != null)
224       _manifestLoader.addManifestClassPath(classPath, pwd);
225     else
226       loader.addManifestClassPath(classPath, pwd);
227   }
228   
229   /**
230    * Expand an archive. The _archiveExpandLock must be obtained before the
231    * expansion.
232    */

233   private boolean expandArchiveImpl()
234     throws IOException JavaDoc
235   {
236     Path archivePath = getArchivePath();
237
238     if (archivePath == null)
239       return true;
240     
241     if (! archivePath.canRead())
242       return true;
243
244     Path expandDir = getRootDirectory();
245     Path parent = expandDir.getParent();
246     
247     try {
248       parent.mkdirs();
249     } catch (Throwable JavaDoc e) {
250     }
251     
252     Path dependPath = expandDir.lookup("META-INF/resin-war.digest");
253     Depend depend = null;
254
255       // XXX: change to a hash
256
if (dependPath.canRead()) {
257       ReadStream is = null;
258       try {
259         is = dependPath.openRead();
260
261     String JavaDoc line = is.readLine();
262
263         long digest;
264
265     if (line != null) {
266       digest = Long.parseLong(line.trim());
267
268       depend = new Depend(archivePath, digest);
269
270       if (! depend.isModified())
271         return true;
272     }
273       } catch (Throwable JavaDoc e) {
274     log.log(Level.FINE, e.toString(), e);
275       } finally {
276     if (is != null)
277       is.close();
278       }
279     }
280
281     if (depend == null)
282       depend = new Depend(archivePath);
283
284     try {
285       if (log.isLoggable(Level.INFO))
286         getLog().info("expanding " + archivePath + " to " + expandDir);
287
288       removeExpandDirectory(expandDir);
289
290       expandDir.mkdirs();
291
292       ReadStream rs = archivePath.openRead();
293       ZipInputStream JavaDoc zis = new ZipInputStream JavaDoc(rs);
294
295       try {
296         ZipEntry JavaDoc entry;
297
298         byte []buffer = new byte[1024];
299       
300         while ((entry = zis.getNextEntry()) != null) {
301           String JavaDoc name = entry.getName();
302           Path path = expandDir.lookup(name);
303
304           if (entry.isDirectory())
305             path.mkdirs();
306           else {
307             long length = entry.getSize();
308             long lastModified = entry.getTime();
309             path.getParent().mkdirs();
310
311             WriteStream os = path.openWrite();
312             try {
313               int len;
314               while ((len = zis.read(buffer, 0, buffer.length)) > 0)
315                 os.write(buffer, 0, len);
316             } catch (IOException JavaDoc e) {
317               log.log(Level.FINE, e.toString(), e);
318             } finally {
319               os.close();
320             }
321
322             if (lastModified > 0)
323               path.setLastModified(lastModified);
324           }
325         }
326       } finally {
327         try {
328           zis.close();
329         } catch (IOException JavaDoc e) {
330         }
331
332     rs.close();
333       }
334     } catch (IOException JavaDoc e) {
335       log.log(Level.WARNING, e.toString(), e);
336       // If the jar is incomplete, it should throw an exception here.
337
return false;
338     }
339     
340     try {
341       dependPath.getParent().mkdirs();
342       WriteStream os = dependPath.openWrite();
343
344       os.println(depend.getDigest());
345       
346       os.close();
347     } catch (Throwable JavaDoc e) {
348       log.log(Level.WARNING, e.toString(), e);
349     }
350
351     return true;
352   }
353
354   /**
355    * Recursively remove all files in a directory. Used for wars when
356    * they change.
357    *
358    * @param path root directory to start removal
359    */

360   protected void removeExpandDirectory(Path path)
361   {
362     String JavaDoc prefix = path.getPath();
363
364     if (! prefix.endsWith("/"))
365       prefix = prefix + "/";
366
367     removeExpandDirectory(path, prefix);
368   }
369
370   /**
371    * Recursively remove all files in a directory. Used for wars when
372    * they change.
373    *
374    * @param dir root directory to start removal
375    */

376   protected void removeExpandDirectory(Path path, String JavaDoc prefix)
377   {
378     try {
379       if (path.isDirectory()) {
380         String JavaDoc []list = path.list();
381         for (int i = 0; list != null && i < list.length; i++) {
382           removeExpandDirectory(path.lookup(list[i]), prefix);
383         }
384       }
385
386       removeExpandFile(path, prefix);
387     } catch (Throwable JavaDoc e) {
388       log.log(Level.WARNING, e.toString(), e);
389     }
390   }
391
392   /**
393    * Removes an expanded file.
394    */

395   protected void removeExpandFile(Path path, String JavaDoc prefix)
396     throws IOException JavaDoc
397   {
398     if (_expandCleanupFileSet == null ||
399     _expandCleanupFileSet.isMatch(path, prefix))
400       path.remove();
401   }
402
403   /**
404    * Returns the hash code.
405    */

406   public int hashCode()
407   {
408     return getId().hashCode();
409   }
410
411   /**
412    * Returns equality.
413    */

414   public boolean equals(Object JavaDoc o)
415   {
416     // server/125g
417
if (o == null || ! getClass().equals(o.getClass()))
418       return false;
419
420     DeployController controller = (DeployController) o;
421
422     // XXX: s/b getRootDirectory?
423
return getId().equals(controller.getId());
424   }
425 }
426
Popular Tags