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(StashPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.STASH);
37 annotationProductMap.put(RefAppPluginModuleCreator.class.getName(), PluginModuleCreatorRegistry.REFAPP);
38 }
39
40 private final PluginModuleCreatorRegistry pluginModuleCreatorRegistry;
41
42 public ModuleCreatorAnnotationParser(PluginModuleCreatorRegistry pluginModuleCreatorRegistry)
43 {
44 super();
45 this.pluginModuleCreatorRegistry = pluginModuleCreatorRegistry;
46 }
47
48 public void parse() throws Exception
49 {
50 ClassLoader oldLoader = Thread.currentThread()
51 .getContextClassLoader();
52 Thread.currentThread()
53 .setContextClassLoader(getClass().getClassLoader());
54 parse(MODULE_PACKAGE, new ModuleClassVisitor());
55 Thread.currentThread()
56 .setContextClassLoader(oldLoader);
57 }
58
59 public void parse(String basePackage) throws Exception
60 {
61 ClassLoader oldLoader = Thread.currentThread()
62 .getContextClassLoader();
63 Thread.currentThread()
64 .setContextClassLoader(getClass().getClassLoader());
65 parse(basePackage, new ModuleClassVisitor());
66 Thread.currentThread()
67 .setContextClassLoader(oldLoader);
68 }
69
70 public class ModuleClassVisitor extends EmptyVisitor
71 {
72
73 private String visitedClassname;
74 private boolean isModuleCreator;
75
76 @Override
77 public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)
78 {
79 this.visitedClassname = normalize(name);
80 String iface = PluginModuleCreator.class.getName()
81 .replace('.', '/');
82 this.isModuleCreator = ArrayUtils.contains(interfaces, iface);
83 if (!isModuleCreator)
84 {
85 this.isModuleCreator = superHasInterface(superName, iface);
86 }
87 }
88
89 private boolean superHasInterface(String superName, String interfaceName)
90 {
91 boolean hasInterface = false;
92
93 if (normalize(superName).equals("java.lang.Object"))
94 {
95 return hasInterface;
96 }
97
98 ClassLoader classLoader = Thread.currentThread().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 }