001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: ClasspathUtils.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.tools;
009:
010: import com.uwyn.rife.config.RifeConfig;
011: import java.io.File;
012: import java.io.FileFilter;
013: import java.io.IOException;
014: import java.io.UnsupportedEncodingException;
015: import java.lang.reflect.InvocationTargetException;
016: import java.lang.reflect.Method;
017: import java.net.URL;
018: import java.net.URLClassLoader;
019: import java.net.URLDecoder;
020: import java.util.ArrayList;
021: import java.util.Enumeration;
022: import java.util.List;
023: import java.util.jar.JarEntry;
024: import java.util.jar.JarFile;
025: import java.util.regex.Pattern;
026:
027: public abstract class ClasspathUtils {
028: public static ArrayList<String> getResourcesInDirectory(
029: String directory) {
030: return getResourcesInDirectory(directory, true, null);
031: }
032:
033: public static ArrayList<String> getResourcesInDirectory(
034: String directory, FileFilter filter) {
035: return getResourcesInDirectory(directory, true, filter);
036: }
037:
038: public static ArrayList<String> getResourcesInDirectory(
039: String directory, boolean excludeJavaHomePaths) {
040: return getResourcesInDirectory(directory, excludeJavaHomePaths,
041: null);
042: }
043:
044: public static ArrayList<String> getResourcesInDirectory(
045: String directory, boolean excludeJavaHomePaths,
046: FileFilter filter) {
047: ArrayList<String> resources = new ArrayList<String>();
048: ArrayList<URL> classpath_components = ClasspathComponentsSingleton.INSTANCE
049: .getClasspathComponents();
050: String classpath_component_filename = null;
051: File classpath_component_file = null;
052: String java_home = System.getProperty("java.home");
053:
054: for (URL classpath_component : classpath_components) {
055: try {
056: classpath_component_filename = URLDecoder.decode(
057: classpath_component.getFile(), "ISO-8859-1");
058: } catch (UnsupportedEncodingException e) {
059: // should never fail, it's a standard encoding
060: }
061:
062: if (null != classpath_component_filename
063: && (excludeJavaHomePaths && !classpath_component_filename
064: .startsWith(java_home))) {
065: classpath_component_file = new File(
066: classpath_component_filename);
067:
068: Pattern[] included = new Pattern[1];
069: if (directory != null) {
070: if (File.separatorChar != '/') {
071: directory = directory.replace('/',
072: File.separatorChar);
073: }
074:
075: included[0] = Pattern.compile("^"
076: + StringUtils.encodeRegexp(directory)
077: + ".*");
078: }
079:
080: Pattern[] excluded = new Pattern[1];
081: if (directory != null) {
082: excluded[0] = Pattern.compile(".*\\.svn.*");
083: }
084:
085: if ((null == filter || filter
086: .accept(classpath_component_file))
087: && classpath_component_file.canRead()) {
088: ArrayList<String> filelist = null;
089: if (classpath_component_file.isFile()
090: && classpath_component_filename
091: .endsWith(".jar")) {
092: try {
093: JarFile jar_file = new JarFile(
094: classpath_component_file);
095: Enumeration<JarEntry> jar_entries = jar_file
096: .entries();
097: JarEntry jar_entry = null;
098: String entry_name = null;
099: filelist = new ArrayList<String>(jar_file
100: .size());
101: while (jar_entries.hasMoreElements()) {
102: jar_entry = jar_entries.nextElement();
103: if (!jar_entry.isDirectory()) {
104: entry_name = jar_entry.getName();
105: if (StringUtils.filter(entry_name,
106: included, excluded)) {
107: filelist.add(entry_name);
108: }
109: }
110: }
111: } catch (IOException e) {
112: // don't propagate this since this classpath entry will just be ignored when an error occurs
113: }
114: } else if (classpath_component_file.isDirectory()) {
115: filelist = FileUtils.getFileList(
116: classpath_component_file, included,
117: excluded);
118: }
119:
120: if (null != filelist) {
121: for (String filelist_entry : filelist) {
122: filelist_entry = filelist_entry.replace(
123: File.separatorChar, '/');
124: if (!resources.contains(filelist_entry)) {
125: resources.add(filelist_entry);
126: }
127: }
128: }
129: }
130: }
131: }
132:
133: return resources;
134: }
135:
136: private static ArrayList<String> getClassPathCandidates(
137: ClassLoader classloader) {
138: // try to obtain the base resin classloader class
139: Class resin_classloader = null;
140: try {
141: resin_classloader = classloader
142: .loadClass("com.caucho.util.DynamicClassLoader");
143: } catch (ClassNotFoundException e) {
144: resin_classloader = null;
145: }
146:
147: ArrayList<String> classpath_candidates = new ArrayList<String>();
148: URL[] classloader_urls = null;
149: do {
150: // handle regular URLClassLoader classes
151: if (classloader instanceof URLClassLoader) {
152: classloader_urls = ((URLClassLoader) classloader)
153: .getURLs();
154: for (URL classloader_url : classloader_urls) {
155: if (classloader_url.getProtocol().equals("file")) {
156: try {
157: classpath_candidates.add(URLDecoder.decode(
158: classloader_url.getPath(),
159: "ISO-8859-1"));
160: } catch (UnsupportedEncodingException e) {
161: // should never fail, it's a standard encoding
162: }
163: }
164: }
165: }
166: // handle resin classloaders
167: else if (resin_classloader != null
168: && resin_classloader.isAssignableFrom(classloader
169: .getClass())) {
170: try {
171: Method method = resin_classloader
172: .getDeclaredMethod("getClassPath",
173: (Class[]) null);
174: String resin_classpath = (String) method.invoke(
175: classloader, (Object[]) null);
176: classpath_candidates.addAll(StringUtils.split(
177: resin_classpath, File.pathSeparator));
178: } catch (SecurityException e) {
179: // do nothing
180: } catch (NoSuchMethodException e) {
181: // do nothing
182: } catch (IllegalArgumentException e) {
183: // do nothing
184: } catch (InvocationTargetException e) {
185: // do nothing
186: } catch (IllegalAccessException e) {
187: // do nothing
188: }
189: }
190: classloader = classloader.getParent();
191: } while (classloader != null);
192:
193: return classpath_candidates;
194: }
195:
196: public static String getClassPath(Class reference) {
197: // construct the classpath string from the list
198: return StringUtils.join(getClassPathAsList(reference),
199: File.pathSeparator);
200: }
201:
202: public static List<String> getClassPathAsList(Class reference) {
203: ArrayList<String> classpath = new ArrayList<String>();
204:
205: // try to obtain the classpath element through the hierachy
206: // of classloaders
207: ArrayList<String> classpath_candidates = new ArrayList<String>();
208: classpath_candidates.addAll(getClassPathCandidates(Thread
209: .currentThread().getContextClassLoader()));
210: classpath_candidates.addAll(getClassPathCandidates(reference
211: .getClassLoader()));
212:
213: // try to detect the location of the RIFE classes
214: String current_class_file = ClasspathUtils.class.getName()
215: .replace('.', '/')
216: + ".class";
217: URL rife_classpath_resource = reference.getClassLoader()
218: .getResource(current_class_file);
219: if (rife_classpath_resource != null) {
220: String rife_classpath_entry = rife_classpath_resource
221: .toExternalForm();
222: if (rife_classpath_entry.startsWith("jar:file:")) {
223: rife_classpath_entry = rife_classpath_entry
224: .substring("jar:file:".length());
225: rife_classpath_entry = rife_classpath_entry.substring(
226: 0, rife_classpath_entry.indexOf("!"));
227: } else if (rife_classpath_entry.startsWith("file:")) {
228: rife_classpath_entry = rife_classpath_entry
229: .substring("file:".length());
230: rife_classpath_entry = rife_classpath_entry.substring(
231: 0, rife_classpath_entry
232: .indexOf(current_class_file));
233: } else {
234: rife_classpath_entry = null;
235: }
236:
237: if (rife_classpath_entry != null) {
238: classpath_candidates.add(rife_classpath_entry);
239: }
240: }
241:
242: // include the system-wide classpath properties for completeness
243: classpath_candidates.addAll(StringUtils.split(RifeConfig.Global
244: .getApplicationClassPath(), File.pathSeparator));
245: classpath_candidates.addAll(StringUtils
246: .split(System.getProperty("sun.boot.class.path"),
247: File.pathSeparator));
248: classpath_candidates.addAll(StringUtils.split(System
249: .getProperty("java.class.path"), File.pathSeparator));
250:
251: // iterate over the classpath candidate entries, validate them
252: // and add them to the classpath if they're no already present
253: File path_file = null;
254: for (String path : classpath_candidates) {
255: if (!classpath.contains(path)) {
256: path_file = new File(path);
257: if (path_file.exists()
258: && path_file.canRead()
259: && (path_file.isDirectory() || (path_file
260: .isFile() && path.endsWith(".jar")))) {
261: classpath.add(path);
262: }
263: }
264: }
265:
266: return classpath;
267: }
268: }
|