View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.util;
5   
6   import java.io.BufferedReader;
7   import java.io.File;
8   import java.io.IOException;
9   import java.io.InputStreamReader;
10  import java.net.MalformedURLException;
11  import java.net.URL;
12  import java.net.URLClassLoader;
13  import java.util.ArrayList;
14  import java.util.List;
15  import java.util.StringTokenizer;
16  import java.util.logging.Level;
17  import java.util.logging.Logger;
18  
19  import org.apache.commons.io.IOUtils;
20  
21  /**
22   * Create a ClassLoader which loads classes using a CLASSPATH like String.
23   * If the String looks like a URL to a file (e.g. starts with <code>file://</code>)
24   * the file will be read with each line representing an path on the classpath.
25   *
26   * @author Edwin Chan
27   */
28  public class ClasspathClassLoader extends URLClassLoader {
29  
30      private static final Logger LOG = Logger.getLogger(ClasspathClassLoader.class.getName());
31  
32      public ClasspathClassLoader(String classpath, ClassLoader parent) throws IOException {
33          super(initURLs(classpath), parent);
34      }
35  
36      private static URL[] initURLs(String classpath) throws IOException {
37          if (classpath == null) {
38              throw new IllegalArgumentException("classpath argument cannot be null");
39          }
40          final List<URL> urls = new ArrayList<URL>();
41          if (classpath.startsWith("file://")) {
42              // Treat as file URL
43              addFileURLs(urls, new URL(classpath));
44          } else {
45              // Treat as classpath
46              addClasspathURLs(urls, classpath);
47          }
48          return urls.toArray(new URL[urls.size()]);
49      }
50  
51      private static void addClasspathURLs(final List<URL> urls, final String classpath) throws MalformedURLException {
52          StringTokenizer toker = new StringTokenizer(classpath, File.pathSeparator);
53          while (toker.hasMoreTokens()) {
54              String token = toker.nextToken();
55              LOG.log(Level.FINE, "Adding classpath entry: <{0}>", token);
56              urls.add(createURLFromPath(token));
57          }
58      }
59  
60      private static void addFileURLs(List<URL> urls, URL fileURL) throws IOException {
61          BufferedReader in = null;
62          try {
63              in = new BufferedReader(new InputStreamReader(fileURL.openStream()));
64              String line;
65              while ((line = in.readLine()) != null) {
66                  LOG.log(Level.FINE, "Read classpath entry line: <{0}>", line);
67                  line = line.trim();
68                  if (line.length() > 0) {
69                      LOG.log(Level.FINE, "Adding classpath entry: <{0}>", line);
70                      urls.add(createURLFromPath(line));
71                  }
72              }
73          } finally {
74              IOUtils.closeQuietly(in);
75          }
76      }
77  
78      private static URL createURLFromPath(String path) throws MalformedURLException {
79          File file = new File(path);
80          return file.getAbsoluteFile().toURI().toURL();
81      }
82  
83      /**
84       * {@inheritDoc}
85       */
86      @Override
87      public String toString() {
88          StringBuilder sb = new StringBuilder(getClass().getSimpleName());
89          sb.append("[[");
90          StringUtil.asStringOn(sb, getURLs(), ":");       
91          sb.append("] parent: ");
92          sb.append(getParent());
93          sb.append(']');
94  
95          return sb.toString();
96      }
97  }