View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.chukwa.util;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.UnsupportedEncodingException;
24  import java.net.JarURLConnection;
25  import java.net.URL;
26  import java.net.URLDecoder;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collections;
30  import java.util.Enumeration;
31  import java.util.List;
32  import java.util.jar.JarEntry;
33  import java.util.jar.JarFile;
34  
35  import org.apache.log4j.Logger;
36  
37  public class ClassUtils {
38    static Logger log = Logger.getLogger(ClassUtils.class);
39    
40    /**
41     * Attempts to list all the classes in the specified package as determined
42     * by the context class loader
43     * 
44     * @param pckgname
45     *            the package name to search
46     * @return a list of classes that exist within that package
47     * @throws ClassNotFoundException
48     *             if something went wrong
49     */
50    public static List<Class> getClassesForPackage(String pckgname)
51        throws ClassNotFoundException {
52      // This will hold a list of directories matching the pckgname.
53      // There may be more than one if a package is split over multiple jars/paths
54      List<Class> classes = new ArrayList<Class>();
55      ArrayList<File> directories = new ArrayList<File>();
56      try {
57        ClassLoader cld = Thread.currentThread().getContextClassLoader();
58        if (cld == null) {
59          throw new ClassNotFoundException("Can't get class loader.");
60        }
61        // Ask for all resources for the path
62        Enumeration<URL> resources = cld.getResources(pckgname.replace('.', '/'));
63        while (resources.hasMoreElements()) {
64          URL res = resources.nextElement();
65          if (res.getProtocol().equalsIgnoreCase("jar")) {
66            JarURLConnection conn = (JarURLConnection) res.openConnection();
67            JarFile jar = conn.getJarFile();
68            for (JarEntry e : Collections.list(jar.entries())) {
69  
70              if (e.getName().startsWith(pckgname.replace('.', '/'))
71                  && e.getName().endsWith(".class") && !e.getName().contains("$")) {
72                String className = e.getName().replace("/", ".").substring(0,
73                    e.getName().length() - 6);
74                classes.add(Class.forName(className));
75              }
76            }
77          } else
78            directories.add(new File(URLDecoder.decode(res.getPath(), "UTF-8")));
79        }
80      } catch (NullPointerException x) {
81        throw new ClassNotFoundException(pckgname + " does not appear to be "
82            + "a valid package (Null pointer exception)");
83      } catch (UnsupportedEncodingException encex) {
84        throw new ClassNotFoundException(pckgname + " does not appear to be "
85            + "a valid package (Unsupported encoding)");
86      } catch (IOException ioex) {
87        throw new ClassNotFoundException("IOException was thrown when trying "
88            + "to get all resources for " + pckgname);
89      }
90  
91      // For every directory identified capture all the .class files
92      for (File directory : directories) {
93        if (directory.exists()) {
94          // Get the list of the files contained in the package
95          String[] files = directory.list();
96          for (String file : files) {
97            // we are only interested in .class files
98            if (file.endsWith(".class")) {
99              // removes the .class extension
100             classes.add(Class.forName(pckgname + '.'
101                 + file.substring(0, file.length() - 6)));
102           }
103         }
104       } else {
105         throw new ClassNotFoundException(pckgname + " (" + directory.getPath()
106             + ") does not appear to be a valid package");
107       }
108     }
109     return classes;
110   }
111 
112   public static List<Class> getClassessOfInterface(String thePackage,
113       Class theInterface) {
114     List<Class> classList = new ArrayList<Class>();
115     try {
116       for (Class discovered : getClassesForPackage(thePackage)) {
117         if (Arrays.asList(discovered.getInterfaces()).contains(theInterface)) {
118           classList.add(discovered);
119         }
120       }
121     } catch (ClassNotFoundException ex) {
122       log.error(ExceptionUtil.getStackTrace(ex));
123     }
124 
125     return classList;
126   }
127   
128 
129 }