1 package com.atlassian.plugins.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.*;
8 import com.atlassian.plugins.codegen.modules.PluginModuleCreator;
9 import com.atlassian.plugins.codegen.modules.PluginModuleCreatorRegistry;
10
11 import org.apache.commons.io.IOUtils;
12 import org.apache.commons.lang.ArrayUtils;
13 import org.apache.commons.lang.StringUtils;
14 import org.objectweb.asm.AnnotationVisitor;
15 import org.objectweb.asm.ClassReader;
16 import org.objectweb.asm.FieldVisitor;
17 import org.objectweb.asm.MethodVisitor;
18 import org.objectweb.asm.commons.EmptyVisitor;
19
20
21
22
23 public class ModuleCreatorAnnotationParser extends AbstractAnnotationParser
24 {
25
26 public static final String MODULE_PACKAGE = "com.atlassian.plugins.codegen.modules";
27 protected static final Map<String, String> annotationProductMap = new HashMap<String, String>();
28
29 static
30 {
31 annotationProductMap.put(JiraPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.JIRA);
32 annotationProductMap.put(ConfluencePluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.CONFLUENCE);
33 annotationProductMap.put(BambooPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.BAMBOO);
34 annotationProductMap.put(CrowdPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.CROWD);
35 annotationProductMap.put(FeCruPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.FECRU);
36 annotationProductMap.put(RefAppPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.REFAPP);
37 }
38
39 private final PluginModuleCreatorRegistry pluginModuleCreatorRegistry;
40
41 public ModuleCreatorAnnotationParser(PluginModuleCreatorRegistry pluginModuleCreatorRegistry)
42 {
43 super();
44 this.pluginModuleCreatorRegistry = pluginModuleCreatorRegistry;
45 }
46
47 public void parse() throws Exception
48 {
49 ClassLoader oldLoader = Thread.currentThread()
50 .getContextClassLoader();
51 Thread.currentThread()
52 .setContextClassLoader(getClass().getClassLoader());
53 parse(MODULE_PACKAGE, new ModuleClassVisitor());
54 Thread.currentThread()
55 .setContextClassLoader(oldLoader);
56 }
57
58 public void parse(String basePackage) throws Exception
59 {
60 ClassLoader oldLoader = Thread.currentThread()
61 .getContextClassLoader();
62 Thread.currentThread()
63 .setContextClassLoader(getClass().getClassLoader());
64 parse(basePackage, new ModuleClassVisitor());
65 Thread.currentThread()
66 .setContextClassLoader(oldLoader);
67 }
68
69 public class ModuleClassVisitor extends EmptyVisitor
70 {
71
72 private String visitedClassname;
73 private boolean isModuleCreator;
74
75 @Override
76 public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)
77 {
78 this.visitedClassname = normalize(name);
79 String iface = PluginModuleCreator.class.getName()
80 .replace('.', '/');
81 this.isModuleCreator = ArrayUtils.contains(interfaces, iface);
82 if (!isModuleCreator)
83 {
84 this.isModuleCreator = superHasInterface(superName, iface);
85 }
86 }
87
88 private boolean superHasInterface(String superName, String interfaceName)
89 {
90 boolean hasInterface = false;
91
92 if (normalize(superName).equals("java.lang.Object"))
93 {
94 return hasInterface;
95 }
96
97 ClassLoader classLoader = Thread.currentThread()
98 .getContextClassLoader();
99 String path = superName.replace('.', '/');
100
101 InputStream is = null;
102 try
103 {
104 is = classLoader.getResourceAsStream(path + ".class");
105 if (null != is)
106 {
107
108 ClassReader classReader = new ClassReader(is);
109 hasInterface = ArrayUtils.contains(classReader.getInterfaces(), interfaceName);
110 if (!hasInterface)
111 {
112 hasInterface = superHasInterface(classReader.getSuperName(), interfaceName);
113 }
114 }
115 } catch (Exception e)
116 {
117
118 } finally
119 {
120 IOUtils.closeQuietly(is);
121 }
122
123 return hasInterface;
124 }
125
126 @Override
127 public AnnotationVisitor visitAnnotation(String annotationName, boolean isVisible)
128 {
129 String normalizedName = normalize(annotationName);
130
131 if (isModuleCreator && annotationProductMap.containsKey(normalizedName))
132 {
133 return new ProductCreatorAnnotationVisitor(normalizedName);
134 }
135
136 return null;
137 }
138
139
140 @Override
141 public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings)
142 {
143 return null;
144 }
145
146 @Override
147 public FieldVisitor visitField(int i, String s, String s1, String s2, Object o)
148 {
149 return null;
150 }
151
152 private class ProductCreatorAnnotationVisitor extends EmptyVisitor
153 {
154
155 private String annotationName;
156
157 private ProductCreatorAnnotationVisitor(String annotationName)
158 {
159 this.annotationName = annotationName;
160 }
161
162 @Override
163 public void visitEnd()
164 {
165
166 super.visitEnd();
167
168 String productId = annotationProductMap.get(annotationName);
169 if (StringUtils.isNotBlank(productId))
170 {
171 try
172 {
173 PluginModuleCreator creator = (PluginModuleCreator) Class.forName(visitedClassname)
174 .newInstance();
175 pluginModuleCreatorRegistry.registerModuleCreator(productId, creator);
176 } catch (Exception e)
177 {
178 e.printStackTrace();
179
180 }
181 }
182 }
183 }
184 }
185 }