ClasspathClassLoader.java
001 package net.sourceforge.pmd.util;
002 
003 import java.io.BufferedReader;
004 import java.io.File;
005 import java.io.IOException;
006 import java.io.InputStreamReader;
007 import java.net.MalformedURLException;
008 import java.net.URL;
009 import java.net.URLClassLoader;
010 import java.util.ArrayList;
011 import java.util.List;
012 import java.util.StringTokenizer;
013 import java.util.logging.Level;
014 import java.util.logging.Logger;
015 
016 /**
017  * Create a ClassLoader which loads classes using a CLASSPATH like String.
018  * If the String looks like a URL to a file (e.g. starts with <code>file://</code>)
019  * the file will be read with each line representing an path on the classpath.
020  *
021  @author Edwin Chan
022  */
023 public class ClasspathClassLoader extends URLClassLoader {
024 
025     private static final Logger LOG = Logger.getLogger(ClasspathClassLoader.class.getName());
026 
027     public ClasspathClassLoader(String classpath, ClassLoader parentthrows IOException {
028         super(initURLs(classpath), parent);
029     }
030 
031     private static URL[] initURLs(String classpaththrows IOException {
032         if (classpath == null) {
033             throw new IllegalArgumentException("classpath argument cannot be null");
034         }
035         final List<URL> urls = new ArrayList<URL>();
036         if (classpath.startsWith("file://")) {
037             // Treat as file URL
038             addFileURLs(urls, new URL(classpath));
039         else {
040             // Treat as classpath
041             addClasspathURLs(urls, classpath);
042         }
043         return urls.toArray(new URL[urls.size()]);
044     }
045 
046     private static void addClasspathURLs(final List<URL> urls, final String classpaththrows MalformedURLException {
047         StringTokenizer toker = new StringTokenizer(classpath, File.pathSeparator);
048         while (toker.hasMoreTokens()) {
049             String token = toker.nextToken();
050             LOG.log(Level.FINE, "Adding classpath entry: <{0}>", token);
051             urls.add(createURLFromPath(token));
052         }
053     }
054 
055     private static void addFileURLs(List<URL> urls, URL fileURLthrows IOException {
056         BufferedReader in = null;
057         try {
058             in = new BufferedReader(new InputStreamReader(fileURL.openStream()));
059             String line;
060             while ((line = in.readLine()) != null) {
061                 LOG.log(Level.FINE, "Read classpath entry line: <{0}>", line);
062                 line = line.trim();
063                 if (line.length() 0) {
064                     LOG.log(Level.FINE, "Adding classpath entry: <{0}>", line);
065                     urls.add(createURLFromPath(line));
066                 }
067             }
068             in.close();
069         finally {
070             if (in != null) {
071                 try {
072                     in.close();
073                 catch (IOException e) {
074                     LOG.log(Level.SEVERE, "IOException while closing InputStream", e);
075                 }
076             }
077         }
078     }
079 
080     private static URL createURLFromPath(String paththrows MalformedURLException {
081         File file = new File(path);
082         return file.getAbsoluteFile().toURI().toURL();
083     }
084 
085     /**
086      * {@inheritDoc}
087      */
088     @Override
089     public String toString() {
090         StringBuilder sb = new StringBuilder();
091         sb.append(getClass().getSimpleName());
092         sb.append("[[");
093         boolean first = true;
094         for (URL url : getURLs()) {
095             if (!first) {
096                 sb.append(':');
097             }
098             first = false;
099             sb.append(url);
100         }
101         sb.append("] parent: ");
102         sb.append(getParent());
103         sb.append(']');
104 
105         return sb.toString();
106     }
107 }