View Javadoc

1   /*
2    * $Id: InterfaceClassScanner.java 19191 2010-08-25 21:05:23Z tcarlson $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule.util.scan;
11  
12  import org.mule.util.scan.annotations.ClosableClassReader;
13  
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.net.URL;
17  
18  import org.objectweb.asm.ClassReader;
19  import org.objectweb.asm.commons.EmptyVisitor;
20  
21  /**
22   * Will determine if the class provide is assignable from the interface class provied.
23   */
24  public class InterfaceClassScanner extends EmptyVisitor implements ClassScanner
25  {
26      private Class interfaceClass;
27  
28      private boolean match;
29  
30      private String className;
31  
32      private ClassLoader classLoader;
33  
34      public InterfaceClassScanner(Class interfaceClass)
35      {
36          this(interfaceClass, Thread.currentThread().getContextClassLoader());
37      }
38  
39      public InterfaceClassScanner(Class interfaceClass, ClassLoader classLoader)
40      {
41          if(!interfaceClass.isInterface())
42          {
43              throw new IllegalArgumentException("The class need to be an interface");
44          }
45          this.interfaceClass = interfaceClass;
46  
47          this.classLoader = classLoader;
48      }
49  
50      public void visit(int i, int i1, String s, String s1, String superName, String[] interfaces)
51      {
52          if (interfaces != null && interfaces.length > 0)
53          {
54              for (int j = 0; j < interfaces.length; j++)
55              {
56                  String anInterface = interfaces[j].replace("/", ".");
57                  if (interfaceClass.getName().equals(anInterface))
58                  {
59                      match = true;
60                      className = s;
61                      break;
62                  }
63                  else
64                  {
65                      //No exact match, lets can the Inferface next
66                      ClassScanner scanner = scan(anInterface);
67                      match = scanner.isMatch();
68                      className = s;
69                  }
70  
71              }
72          }
73          //We're processing java.lang.Object
74          else if (superName == null)
75          {
76              return;
77          }
78          else
79          {
80              //Lets check the super class
81              ClassScanner scanner = scan(superName);
82              match = scanner.isMatch();
83              className = scanner.getClassName();
84              //If there is a match we need to set the super class not the subclass that matched
85              if(match)
86              {
87                  className = s;
88              }
89          }
90      }
91  
92      protected ClassScanner scan(String name)
93      {
94          try
95          {
96              InterfaceClassScanner scanner = new InterfaceClassScanner(interfaceClass, classLoader);
97              URL classURL = getClassURL(name);
98              if(classURL==null)
99              {
100                 throw new RuntimeException("Failed to read class URL for name: " + name);
101             }
102             InputStream classStream = classURL.openStream();
103             ClassReader r = new ClosableClassReader(classStream);
104             
105             r.accept(scanner, 0);
106             return scanner;
107         }
108         catch (IOException e)
109         {
110             throw new RuntimeException(name, e);
111         }
112     }
113 
114     public boolean isMatch()
115     {
116         return match;
117     }
118 
119     public String getClassName()
120     {
121         return className;
122     }
123 
124     public URL getClassURL(String className)
125     {
126         String resource = className.replace(".", "/") + ".class";
127         return classLoader.getResource(resource);
128     }
129 }