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