1   package com.atlassian.maven.plugins.amps.codegen.annotations.asm;
2   
3   import java.io.InputStream;
4   import java.util.Map;
5   
6   import com.atlassian.plugins.codegen.annotations.asm.AbstractAnnotationParser;
7   
8   import org.apache.commons.io.IOUtils;
9   import org.apache.commons.lang.ArrayUtils;
10  import org.apache.commons.lang.StringUtils;
11  import org.apache.maven.plugin.logging.Log;
12  import org.objectweb.asm.AnnotationVisitor;
13  import org.objectweb.asm.ClassReader;
14  import org.objectweb.asm.FieldVisitor;
15  import org.objectweb.asm.MethodVisitor;
16  import org.objectweb.asm.commons.EmptyVisitor;
17  
18  /**
19   * @since 3.6
20   */
21  public class CustomFieldTypeLocator extends AbstractAnnotationParser
22  {
23      public static final String JIRA_FIELDS_PACKAGE = "com.atlassian.jira.issue.customfields.impl";
24  
25      private Log log;
26      private Map<String, String> fieldTypeRegistry;
27  
28      public CustomFieldTypeLocator(Map<String, String> fieldTypeRegistry)
29      {
30          this.fieldTypeRegistry = fieldTypeRegistry;
31      }
32  
33      public void parse() throws Exception
34      {
35          parse(JIRA_FIELDS_PACKAGE, new FieldClassVisitor());
36      }
37  
38      public void parse(String basePackage) throws Exception
39      {
40          parse(basePackage, new FieldClassVisitor());
41      }
42  
43      public class FieldClassVisitor extends EmptyVisitor
44      {
45  
46          private String visitedClassname;
47          private boolean isCustomFieldType;
48  
49          @Override
50          public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)
51          {
52              this.visitedClassname = normalize(name);
53              String iface = "com/atlassian/jira/issue/customfields/CustomFieldType";
54  
55              this.isCustomFieldType = false;
56  
57              this.isCustomFieldType = ArrayUtils.contains(interfaces, iface);
58              if (!isCustomFieldType)
59              {
60                  this.isCustomFieldType = superHasInterface(superName, iface);
61              }
62  
63              if (isCustomFieldType)
64              {
65                  String simpleName = StringUtils.substringAfterLast(visitedClassname, ".");
66                  fieldTypeRegistry.put(simpleName, visitedClassname);
67              }
68  
69          }
70  
71          private boolean superHasInterface(String superName, String interfaceName)
72          {
73              boolean hasInterface = false;
74  
75              if (normalize(superName).equals("java.lang.Object"))
76              {
77                  return hasInterface;
78              }
79  
80              ClassLoader classLoader = Thread.currentThread()
81                      .getContextClassLoader();
82              String path = superName.replace('.', '/');
83  
84              InputStream is = null;
85              try
86              {
87                  is = classLoader.getResourceAsStream(path + ".class");
88                  if (null != is)
89                  {
90  
91                      ClassReader classReader = new ClassReader(is);
92                      String[] interfaces = classReader.getInterfaces();
93                      hasInterface = ArrayUtils.contains(classReader.getInterfaces(), interfaceName);
94                      if (!hasInterface)
95                      {
96                          hasInterface = superHasInterface(classReader.getSuperName(), interfaceName);
97                      }
98                  }
99              } catch (Exception e)
100             {
101                 //don't care
102             } finally
103             {
104                 IOUtils.closeQuietly(is);
105             }
106 
107             return hasInterface;
108         }
109 
110         @Override
111         public AnnotationVisitor visitAnnotation(String annotationName, boolean isVisible)
112         {
113             return null;
114         }
115 
116         @Override
117         public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings)
118         {
119             return null;
120         }
121 
122         @Override
123         public FieldVisitor visitField(int i, String s, String s1, String s2, Object o)
124         {
125             return null;
126         }
127     }
128 }