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