View Javadoc
1 /* 2 * Copyright (c) 2001, 2002 The XDoclet team 3 * All rights reserved. 4 */ 5 package xdoclet.util; 6 7 import org.apache.commons.collections.CollectionUtils; 8 import org.apache.commons.collections.Predicate; 9 import org.apache.commons.logging.LogFactory; 10 11 import java.io.File; 12 import java.io.FileFilter; 13 import java.io.IOException; 14 import java.io.FileInputStream; 15 16 import java.net.MalformedURLException; 17 import java.net.URL; 18 19 import java.util.ArrayList; 20 import java.util.Collection; 21 import java.util.Iterator; 22 import java.util.StringTokenizer; 23 import java.util.List; 24 import java.util.jar.Manifest; 25 import java.util.jar.JarFile; 26 import java.util.jar.Attributes; 27 28 import xdoclet.PluginFactory; 29 30 /*** 31 * Finds directories and jars on the classpath. 32 * 33 * @author <a href="mailto:aslak.hellesoy at netcom.no">Aslak Hellesøy</a> 34 * @version $Revision: 1.13 $ 35 */ 36 public class ClasspathManager { 37 public static final JarFilter JAR_FILTER = new JarFilter(); 38 public static final DirFilter DIR_FILTER = new DirFilter(); 39 public static final String PATH_DELIM = System.getProperty("path.separator"); 40 private final String _classpath; 41 42 /*** 43 * Contains directories and jars on the classpath that exist, 44 * regardless of whether they have a descriptor. 45 */ 46 private final Collection _files = new ArrayList(); 47 48 /*** 49 * Constructs a new ClasspathManager. 50 * 51 * @param classpath where plugin jars and directories will be searched for 52 */ 53 public ClasspathManager(String classpath) { 54 if (classpath == null) { 55 throw new IllegalArgumentException("classpath cannot be null"); 56 } 57 58 _classpath = classpath; 59 findExistingClasspathFiles(); 60 } 61 62 public static String getNiceClasspath( String classpath ) { 63 StringBuffer sb = new StringBuffer("\n"); 64 65 for (StringTokenizer st = new StringTokenizer( classpath, System.getProperty("path.separator") ); st.hasMoreTokens(); ) { 66 sb.append(" ").append(st.nextToken()).append("\n"); 67 } 68 69 return sb.toString(); 70 } 71 72 /*** 73 * Gets all the files on the classpath that exist, both directories and files. 74 * 75 * @return Collection of File 76 */ 77 public Collection getFiles() { 78 return _files; 79 } 80 81 /*** 82 * Returns the existing zip/jar files on the classpath. 83 * 84 * @return a Collection of File 85 */ 86 public final Collection getJars() { 87 return CollectionUtils.select(getFiles(), JAR_FILTER); 88 } 89 90 /*** 91 * Returns the existing directories on the classpath. 92 * 93 * @return a Collection of File 94 */ 95 public final Collection getDirectories() { 96 return CollectionUtils.select(getFiles(), DIR_FILTER); 97 } 98 99 /*** 100 * Returns a resource from the classpath, taking the first it finds. 101 * 102 * @param relativePath 103 * @return an URL to the resource or null if not found. 104 */ 105 public URL getResource(String relativePath) { 106 if (relativePath == null) { 107 throw new IllegalArgumentException("relativePath can't be null"); 108 } 109 110 for (Iterator files = getFiles().iterator(); files.hasNext();) { 111 File file = (File) files.next(); 112 113 try { 114 URL fileUrl = file.toURL(); 115 116 if (FileUtils.isJar(file)) { 117 try { 118 URL resourceURL = new URL("jar:" + fileUrl.toExternalForm() + "!/" + relativePath); 119 120 try { 121 resourceURL.openStream(); // if we don't get an exception here, the entry exists. 122 123 return resourceURL; 124 } catch (IOException e) { 125 } 126 } catch (IOException ignore) { 127 } 128 } else if (file.isDirectory()) { 129 File resourceFile = new File(fileUrl.getFile(), relativePath); 130 131 if (resourceFile.exists()) { 132 return resourceFile.toURL(); 133 } 134 } 135 } catch (MalformedURLException ignore) { 136 } 137 } 138 139 return null; 140 } 141 142 /*** 143 * Finds existing files and directories on the classpath. 144 */ 145 private void findExistingClasspathFiles() { 146 StringTokenizer pathTokenizer = new StringTokenizer(_classpath, PATH_DELIM); 147 148 while (pathTokenizer.hasMoreTokens()) { 149 File file = new File(pathTokenizer.nextToken()).getAbsoluteFile(); 150 151 if (file.exists()) { 152 _files.add(file); 153 } else { 154 LogFactory.getLog(ClasspathManager.class).warn("The file " + file.getAbsolutePath() 155 + " was on the classpath, but doesn't exist."); 156 } 157 } 158 } 159 160 /*** 161 * Gets the classpath where plugins are looked for. 162 * @return the classpath where plugins are looked for. 163 */ 164 public String getClasspath() { 165 return _classpath; 166 } 167 168 /*** 169 * Returns all Java Bean classes on the classpath. 170 * @return a List of {@link Class}. 171 */ 172 public List findJavaBeans() { 173 List result = new ArrayList(); 174 for( Iterator files = getFiles().iterator(); files.hasNext(); ) { 175 File dirOrJar = (File) files.next(); 176 result.addAll( findJavaBeans( getClass().getClassLoader(), dirOrJar )); 177 } 178 return result; 179 } 180 181 /*** 182 * Returns a collection of classes that are Java Beans. The Java Bean 183 * classes are found by looking at the MANIFEST.MF file. 184 * 185 * @param beanClassLoader the ClassLoader used to load the bean classes. 186 * @param dirOrJar the directory of jar file containing the classes. 187 * @return a Collection of {@link Class}. 188 */ 189 public static List findJavaBeans( ClassLoader beanClassLoader, File dirOrJar ) { 190 List result = new ArrayList(); 191 192 try { 193 Manifest manifest = null; 194 if (dirOrJar.isDirectory()) { 195 try { 196 manifest = new Manifest(new FileInputStream(new File(dirOrJar, "META-INF/MANIFEST.MF"))); 197 } catch (IOException e) { 198 // Ignore. There was no Manifest here. 199 } 200 } else { 201 try { 202 JarFile jarFile = new JarFile(dirOrJar); 203 204 manifest = jarFile.getManifest(); 205 } catch (IOException e) { 206 // Ignore. Wasn't a jar file. 207 } 208 } 209 210 if (manifest != null) { 211 // Now loop over all entries in the Manifest. 212 for (Iterator entryNames = manifest.getEntries().keySet().iterator(); entryNames.hasNext();) { 213 String entryName = (String) entryNames.next(); 214 // Is it a class? 215 if (entryName.endsWith(".class")) { 216 Attributes attributes = manifest.getAttributes(entryName); 217 LogFactory.getLog(PluginFactory.class).debug("ENTRY:" + entryName); 218 // See if it's a java bean. 219 String javaBean = attributes.getValue("Java-Bean"); 220 221 if ("true".equalsIgnoreCase(javaBean)) { 222 // OK. Get the BeanInfo. 223 String className = entryName.substring(0, entryName.length() - 6); 224 225 className = className.replace('/', '.'); 226 227 // Load the class 228 try { 229 Class beanClass = beanClassLoader.loadClass(className); 230 result.add( beanClass ); 231 } catch (ClassNotFoundException e) { 232 // diagnoseClassLoader( beanClassLoader ); 233 String errorMessage = className 234 + " was declared as a Java-Bean in the manifest, but the class was not found."; 235 236 LogFactory.getLog(PluginFactory.class).error(errorMessage, e); 237 throw new IllegalStateException(errorMessage); 238 } catch (NoClassDefFoundError e) { 239 // diagnoseClassLoader( beanClassLoader ); 240 if( e.getCause() != null ) { 241 e.getCause().printStackTrace(); 242 } 243 String errorMessage = className 244 + " was declared as a Java-Bean in the manifest, but the class was not found."; 245 246 LogFactory.getLog(PluginFactory.class).error(errorMessage, e); 247 throw new IllegalStateException(errorMessage); 248 } 249 } 250 } 251 } 252 } 253 return result; 254 } catch( Exception e ) { 255 throw new IllegalStateException(e.getMessage()); 256 } 257 } 258 259 public static String getPackage( Class clazz ) { 260 return clazz.getName().substring( 0, clazz.getName().lastIndexOf('.')); 261 } 262 263 /*** 264 * Adapter class that makes it possible to use a class as both a 265 * Commons Collections Predicate and FileFilter. 266 */ 267 public abstract static class FileFilterPredicate implements Predicate, FileFilter { 268 public abstract boolean accept(File file); 269 270 public final boolean evaluate(Object o) { 271 return accept((File) o); 272 } 273 } 274 275 public static class JarFilter extends FileFilterPredicate { 276 public boolean accept(File file) { 277 return FileUtils.isJar(file); 278 } 279 } 280 281 public static class DirFilter extends FileFilterPredicate { 282 public boolean accept(File file) { 283 return file.isDirectory(); 284 } 285 } 286 }

This page was automatically generated by Maven