KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jca > ResourceArchive


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  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.jca;
30
31 import com.caucho.config.Config;
32 import com.caucho.config.ConfigException;
33 import com.caucho.jca.cfg.AdminObjectConfig;
34 import com.caucho.jca.cfg.ConnectionDefinition;
35 import com.caucho.jca.cfg.ConnectorConfig;
36 import com.caucho.jca.cfg.MessageListenerConfig;
37 import com.caucho.jca.cfg.ResourceAdapterConfig;
38 import com.caucho.loader.DynamicClassLoader;
39 import com.caucho.loader.EnvironmentBean;
40 import com.caucho.log.Log;
41 import com.caucho.util.L10N;
42 import com.caucho.vfs.Jar;
43 import com.caucho.vfs.Path;
44 import com.caucho.vfs.ReadStream;
45 import com.caucho.vfs.WriteStream;
46
47 import javax.annotation.PostConstruct;
48 import java.io.IOException JavaDoc;
49 import java.io.ObjectInputStream JavaDoc;
50 import java.io.ObjectOutputStream JavaDoc;
51 import java.util.logging.Level JavaDoc;
52 import java.util.logging.Logger JavaDoc;
53 import java.util.zip.ZipEntry JavaDoc;
54 import java.util.zip.ZipInputStream JavaDoc;
55
56 /**
57  * A resource archive (rar)
58  */

59 public class ResourceArchive implements EnvironmentBean {
60   static final L10N L = new L10N(ResourceArchive.class);
61   static final Logger JavaDoc log = Log.open(ResourceArchive.class);
62
63   private ClassLoader JavaDoc _loader;
64   
65   private Path _rootDir;
66
67   private Path _rarPath;
68
69   private ConnectorConfig _config;
70
71   /**
72    * Creates the application.
73    */

74   ResourceArchive()
75   {
76     _loader = Thread.currentThread().getContextClassLoader();
77   }
78
79   /**
80    * Sets the root directory.
81    */

82   public void setRootDirectory(Path rootDir)
83   {
84     _rootDir = rootDir;
85   }
86
87   /**
88    * Sets the root directory.
89    */

90   public Path getRootDirectory()
91   {
92     return _rootDir;
93   }
94
95   /**
96    * Returns the class loader.
97    */

98   public ClassLoader JavaDoc getClassLoader()
99   {
100     return _loader;
101   }
102
103   /**
104    * Sets the path to the .ear file
105    */

106   public void setRarPath(Path rarPath)
107   {
108     _rarPath = rarPath;
109   }
110
111   /**
112    * Returns the name.
113    */

114   public String JavaDoc getDisplayName()
115   {
116     return _config.getDisplayName();
117   }
118
119   /**
120    * Returns the resource adapter class.
121    */

122   public ResourceAdapterConfig getResourceAdapter()
123   {
124     return _config.getResourceAdapter();
125   }
126
127   /**
128    * Returns the transaction support.
129    */

130   public String JavaDoc getTransactionSupport()
131   {
132     if (getResourceAdapter() != null)
133       return getResourceAdapter().getTransactionSupport();
134     else
135       return null;
136   }
137
138   /**
139    * Returns the matching connection factory class.
140    */

141   public ConnectionDefinition getConnectionDefinition(String JavaDoc type)
142   {
143     ResourceAdapterConfig raConfig = _config.getResourceAdapter();
144
145     if (raConfig != null)
146       return raConfig.getConnectionDefinition(type);
147     else
148       return null;
149   }
150
151   /**
152    * Returns the activation spec.
153    */

154   public MessageListenerConfig getMessageListener(String JavaDoc type)
155   {
156     ResourceAdapterConfig raConfig = _config.getResourceAdapter();
157
158     if (raConfig != null)
159       return raConfig.getMessageListener(type);
160     else
161       return null;
162   }
163
164   /**
165    * Returns the managed object definition.
166    */

167   public AdminObjectConfig getAdminObject(String JavaDoc type)
168   {
169     ResourceAdapterConfig raConfig = _config.getResourceAdapter();
170
171     if (raConfig != null)
172       return raConfig.getAdminObject(type);
173     else
174       return null;
175   }
176
177   /**
178    * Configures the resource.
179    */

180   @PostConstruct
181   public void init()
182     throws ConfigException
183   {
184     try {
185       expandRar();
186       
187       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
188       for (; loader != null; loader = loader.getParent()) {
189     if (loader instanceof DynamicClassLoader)
190       break;
191       }
192
193       if (loader == null)
194     throw new ConfigException(L.l("loader issues with resource adapter"));
195
196       addJars((DynamicClassLoader) loader, _rootDir);
197       
198       Path raXml = _rootDir.lookup("META-INF/ra.xml");
199
200       if (! raXml.canRead())
201     throw new ConfigException(L.l("missing ra.xml for rar {0}. .rar files require a META-INF/ra.xml file.",
202                       _rarPath));
203
204       _config = new ConnectorConfig();
205
206       new Config().configure(_config, raXml, "com/caucho/jca/jca.rnc");
207     } catch (ConfigException e) {
208       throw e;
209     } catch (Exception JavaDoc e) {
210       throw new ConfigException(e);
211     }
212
213     log.info("ResourceArchive[" + _config.getDisplayName() + "] loaded");
214   }
215
216   /**
217    * Adds the jars from the rar file to the class loader.
218    */

219   private void addJars(DynamicClassLoader loader, Path path)
220     throws IOException JavaDoc
221   {
222     if (path.getPath().endsWith(".jar")) {
223       loader.addJar(path);
224     }
225     else if (path.isDirectory()) {
226       String JavaDoc []list = path.list();
227
228       for (int i = 0; i < list.length; i++)
229     addJars(loader, path.lookup(list[i]));
230     }
231   }
232
233   /**
234    * Expand an rar file. The _rarExpandLock must be obtained before the
235    * expansion.
236    *
237    * @param rar the rar file
238    * @param expandDir the directory which will contain the rar contents
239    */

240   private void expandRar()
241     throws IOException JavaDoc
242   {
243     Path rar = _rarPath;
244     
245     if (! rar.canRead())
246       return;
247
248     try {
249       _rootDir.mkdirs();
250     } catch (Throwable JavaDoc e) {
251     }
252
253     Path expandDir = _rootDir;
254     Path tempDir = _rootDir.getParent().lookup(".temp");
255     Path dependPath = _rootDir.lookup("META-INF/resin-rar.timestamp");
256
257       // XXX: change to a hash
258
if (dependPath.canRead()) {
259       ReadStream is = null;
260       ObjectInputStream JavaDoc ois = null;
261       try {
262         is = dependPath.openRead();
263         ois = new ObjectInputStream JavaDoc(is);
264
265         long lastModified = ois.readLong();
266         long length = ois.readLong();
267
268         if (lastModified == rar.getLastModified() &&
269             length == rar.getLength())
270           return;
271       } catch (IOException JavaDoc e) {
272       } finally {
273         try {
274           if (ois != null)
275             ois.close();
276         } catch (IOException JavaDoc e) {
277         }
278
279     if (is != null)
280       is.close();
281       }
282     }
283
284     try {
285       if (log.isLoggable(Level.INFO))
286         log.info("expanding rar " + rar + " to " + tempDir);
287
288       
289       if (! tempDir.equals(expandDir)) {
290         tempDir.removeAll();
291       }
292       tempDir.mkdirs();
293
294       ReadStream rs = rar.openRead();
295       ZipInputStream JavaDoc zis = new ZipInputStream JavaDoc(rs);
296
297       try {
298         ZipEntry JavaDoc entry;
299
300         byte []buffer = new byte[1024];
301       
302         while ((entry = zis.getNextEntry()) != null) {
303           String JavaDoc name = entry.getName();
304           Path path = tempDir.lookup(name);
305
306           if (entry.isDirectory())
307             path.mkdirs();
308           else {
309             long length = entry.getSize();
310             long lastModified = entry.getTime();
311             path.getParent().mkdirs();
312
313             WriteStream os = path.openWrite();
314             try {
315               int len;
316               while ((len = zis.read(buffer, 0, buffer.length)) > 0)
317                 os.write(buffer, 0, len);
318             } catch (IOException JavaDoc e) {
319               log.log(Level.FINE, e.toString(), e);
320             } finally {
321               os.close();
322             }
323
324             if (lastModified > 0)
325               path.setLastModified(lastModified);
326           }
327         }
328       } finally {
329         try {
330           zis.close();
331         } catch (IOException JavaDoc e) {
332         }
333
334     rs.close();
335       }
336
337       if (! tempDir.equals(expandDir)) {
338         if (log.isLoggable(Level.INFO))
339           log.info("moving rar " + rar + " to " + expandDir);
340
341         // Close the cached zip streams because on NT that can lock
342
// the filesystem.
343
try {
344           Jar.clearJarCache();
345           removeAll(expandDir);
346         } catch (Throwable JavaDoc e) {
347           Jar.clearJarCache();
348           removeAll(expandDir);
349         }
350
351         moveAll(tempDir, expandDir);
352         removeAll(tempDir);
353       }
354     } catch (IOException JavaDoc e) {
355       log.log(Level.WARNING, e.toString(), e);
356       // If the jar is incomplete, it should throw an exception here.
357
return;
358     }
359     
360     try {
361       dependPath.getParent().mkdirs();
362       WriteStream os = dependPath.openWrite();
363       ObjectOutputStream JavaDoc oos = new ObjectOutputStream JavaDoc(os);
364
365       oos.writeLong(rar.getLastModified());
366       oos.writeLong(rar.getLength());
367       oos.close();
368       os.close();
369     } catch (Throwable JavaDoc e) {
370       log.log(Level.WARNING, e.toString(), e);
371     }
372   }
373
374   /**
375    * Recursively remove all files in a directory. Used for wars when
376    * they change.
377    *
378    * @param dir root directory to start removal
379    */

380   private static void removeAll(Path path)
381   {
382     try {
383       if (path.isDirectory()) {
384         String JavaDoc []list = path.list();
385         for (int i = 0; list != null && i < list.length; i++) {
386           removeAll(path.lookup(list[i]));
387         }
388       }
389         
390       path.remove();
391     } catch (Throwable JavaDoc e) {
392       log.log(Level.WARNING, e.toString(), e);
393     }
394   }
395
396   /**
397    * Move directory A to directory B.
398    *
399    * @param source source directory
400    * @param target target directory
401    */

402   private static void moveAll(Path source, Path target)
403   {
404     try {
405       if (source.isDirectory()) {
406         try {
407           target.mkdirs();
408         } catch (IOException JavaDoc e) {
409         }
410         
411         String JavaDoc []list = source.list();
412         for (int i = 0; list != null && i < list.length; i++) {
413           moveAll(source.lookup(list[i]), target.lookup(list[i]));
414         }
415       }
416       else
417         source.renameTo(target);
418     } catch (IOException JavaDoc e) {
419       log.log(Level.WARNING, e.toString(), e);
420     }
421   }
422 }
423
Popular Tags