KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > util > ClasspathResourcesUtil


1 /**
2  *
3  * Magnolia and its source-code is licensed under the LGPL.
4  * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
5  * When copying, adapting, or redistributing this document in keeping with the guidelines above,
6  * you are required to provide proper attribution to obinary.
7  * If you reproduce or distribute the document without making any substantive modifications to its content,
8  * please use the following attribution line:
9  *
10  * Copyright 1993-2005 obinary Ltd. (http://www.obinary.com) All rights reserved.
11  *
12  */

13 package info.magnolia.cms.util;
14
15 import info.magnolia.cms.core.Path;
16 import info.magnolia.cms.core.SystemProperty;
17
18 import java.io.File JavaDoc;
19 import java.io.FilenameFilter JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.net.URL JavaDoc;
23 import java.net.URLClassLoader JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.jar.JarEntry JavaDoc;
29 import java.util.jar.JarFile JavaDoc;
30
31 import org.apache.commons.io.FileUtils;
32 import org.apache.commons.io.filefilter.TrueFileFilter;
33 import org.apache.commons.lang.StringUtils;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38 /**
39  * Util to find resources in the classpath (WEB-INF/lib and WEB-INF/classes).
40  * @author Philipp Bracher
41  * @version $Revision: 7665 $ ($Author: gjoseph $)
42  */

43 public class ClasspathResourcesUtil {
44
45     /**
46      * logger
47      */

48     private static Logger log = LoggerFactory.getLogger(ClasspathResourcesUtil.class);
49
50     /**
51      * Filter for filtering the resources.
52      * @author Philipp Bracher
53      * @version $Revision: 7665 $ ($Author: gjoseph $)
54      */

55     public static abstract class Filter {
56         public abstract boolean accept(String JavaDoc name);
57     }
58
59     private static boolean isCache() {
60         final String JavaDoc devMode = SystemProperty.getProperty("magnolia.develop");
61         return !"true".equalsIgnoreCase(devMode);
62     }
63
64     /**
65      * Return a collection containing the resource names which passed the filter.
66      * @param filter
67      * @return string array of found resources
68      */

69     public static String JavaDoc[] findResources(Filter JavaDoc filter) {
70
71         Collection JavaDoc resources = new ArrayList JavaDoc();
72
73         ClassLoader JavaDoc cl = getCurrentClassLoader();
74
75         // if the classloader is an URLClassloader we have a better method for discovering resources
76
// whis will also fetch files from jars outside WEB-INF/lib, useful during development
77
if (cl instanceof URLClassLoader JavaDoc) {
78             // tomcat classloader is org.apache.catalina.loader.WebappClassLoader
79
URL JavaDoc[] urls = ((URLClassLoader JavaDoc) cl).getURLs();
80             for (int j = 0; j < urls.length; j++) {
81                 final File JavaDoc tofile = sanitizeToFile(urls[j]);
82                 collectFiles(resources, tofile, filter);
83             }
84         } else {
85             // no way, we have to assume a standard war structure and look in the WEB-INF/lib and WEB-INF/classes dirs
86

87             // read the jars in the lib dir
88
File JavaDoc dir = new File JavaDoc(Path.getAbsoluteFileSystemPath("WEB-INF/lib")); //$NON-NLS-1$
89
if (dir.exists()) {
90                 File JavaDoc[] files = dir.listFiles(new FilenameFilter JavaDoc() {
91
92                     public boolean accept(File JavaDoc file, String JavaDoc name) {
93                         return name.endsWith(".jar");
94                     }
95                 });
96
97                 for (int i = 0; i < files.length; i++) {
98                     collectFiles(resources, files[i], filter);
99                 }
100             }
101
102             // read files in WEB-INF/classes
103
File JavaDoc classFileDir = new File JavaDoc(Path.getAbsoluteFileSystemPath("WEB-INF/classes"));
104             if (classFileDir.exists()) {
105                 collectFiles(resources, classFileDir, filter);
106             }
107         }
108
109         return (String JavaDoc[]) resources.toArray(new String JavaDoc[resources.size()]);
110     }
111
112     protected static File JavaDoc sanitizeToFile(URL JavaDoc url) {
113         String JavaDoc fileUrl = url.getFile();
114
115         // needed for Resin - for some reason, its URLs are formed as jar:file:/absolutepath/foo/bar.jar instead of using the :///abs.. notation
116
fileUrl = StringUtils.removeStart(fileUrl, "file:");
117         fileUrl = StringUtils.removeEnd(fileUrl, "!/");
118
119         return new File JavaDoc(fileUrl);
120     }
121
122     /**
123      * Load resources from jars or directories
124      * @param resources found resources will be added to this collection
125      * @param jarOrDir a File, can be a jar or a directory
126      * @param filter used to filter resources
127      */

128     private static void collectFiles(Collection JavaDoc resources, File JavaDoc jarOrDir, Filter JavaDoc filter) {
129
130         if (!jarOrDir.exists()) {
131             log.warn("missing file: {}", jarOrDir.getAbsolutePath());
132             return;
133         }
134
135         if (jarOrDir.isDirectory()) {
136             if (log.isDebugEnabled()) {
137                 log.debug("looking in dir {}", jarOrDir.getAbsolutePath());
138             }
139
140             Collection JavaDoc files = FileUtils.listFiles(jarOrDir, new TrueFileFilter() {
141             }, new TrueFileFilter() {
142             });
143             for (Iterator JavaDoc iter = files.iterator(); iter.hasNext();) {
144                 File JavaDoc file = (File JavaDoc) iter.next();
145                 String JavaDoc name = StringUtils.substringAfter(file.getPath(), jarOrDir.getPath());
146
147                 // please, be kind to Windows!!!
148
name = StringUtils.replace(name, "\\", "/");
149                 if (!name.startsWith("/")) {
150                     name = "/" + name;
151                 }
152
153                 if (filter.accept(name)) {
154                     resources.add(name);
155                 }
156             }
157         }
158         else if (jarOrDir.getName().endsWith(".jar")) {
159             if (log.isDebugEnabled()) {
160                 log.debug("looking in jar {}", jarOrDir.getAbsolutePath());
161             }
162             JarFile JavaDoc jar;
163             try {
164                 jar = new JarFile JavaDoc(jarOrDir);
165             }
166             catch (IOException JavaDoc e) {
167                 log.error("IOException opening file {}, skipping", jarOrDir.getAbsolutePath());
168                 return;
169             }
170             for (Enumeration JavaDoc em = jar.entries(); em.hasMoreElements();) {
171                 JarEntry JavaDoc entry = (JarEntry JavaDoc) em.nextElement();
172                 if (!entry.isDirectory()) {
173                     if (filter.accept("/" + entry.getName())) {
174                         resources.add("/" + entry.getName());
175                     }
176                 }
177             }
178             try {
179                 jar.close();
180             } catch (IOException JavaDoc e) {
181                 log.error("Failed to close jar file : "+e.getMessage());
182                 log.debug("Failed to close jar file",e);
183             }
184         }
185         else {
186             if (log.isDebugEnabled()) {
187                 log.debug("Unknown (not jar) file in classpath: {}, skipping.", jarOrDir.getName());
188             }
189         }
190
191     }
192
193     public static InputStream JavaDoc getStream(String JavaDoc name) throws IOException JavaDoc {
194         return getStream(name, isCache());
195     }
196
197     /**
198      * Checks last modified and returns the new content if changed and the cache flag is not set to true.
199      * @param name
200      * @return the input stream
201      * @throws IOException
202      */

203     public static InputStream JavaDoc getStream(String JavaDoc name, boolean cache) throws IOException JavaDoc {
204         if (cache) {
205             return getCurrentClassLoader().getResourceAsStream(StringUtils.removeStart(name, "/"));
206         }
207
208         // TODO use the last modified attribute
209
URL JavaDoc url = getResource(name);
210         if (url != null) {
211             return url.openStream();
212         }
213
214         if (log.isDebugEnabled()) {
215             log.debug("Can't find {}", name);
216         }
217         return null;
218     }
219
220     /**
221      * Get the class loader of the current Thread
222      * @return current classloader
223      */

224     private static ClassLoader JavaDoc getCurrentClassLoader() {
225         return Thread.currentThread().getContextClassLoader();
226     }
227
228     /**
229      * Get the resource using the current class laoder. The leading / is removed as the call to class.getResource()
230      * would do.
231      * @param name
232      * @return the resource
233      */

234     public static URL JavaDoc getResource(String JavaDoc name) {
235         return getCurrentClassLoader().getResource(StringUtils.removeStart(name, "/"));
236     }
237
238 }
239
Popular Tags