1 package com.atlassian.plugin.osgi.factory.transform.stage;
2
3 import com.atlassian.plugin.osgi.factory.transform.PluginTransformationException;
4 import com.atlassian.plugin.osgi.factory.transform.TransformContext;
5 import com.atlassian.plugin.osgi.factory.transform.TransformStage;
6 import com.atlassian.plugin.osgi.hostcomponents.HostComponentRegistration;
7 import com.atlassian.plugin.util.ClassLoaderUtils;
8 import org.dom4j.Attribute;
9 import org.dom4j.DocumentHelper;
10 import org.dom4j.XPath;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.Method;
16 import java.util.LinkedHashMap;
17 import java.util.List;
18 import java.util.Map;
19
20 import static com.atlassian.plugin.util.PluginUtils.isAtlassianDevMode;
21
22
23
24
25
26
27 public class ScanDescriptorForHostClassesStage implements TransformStage {
28 private static final Logger log = LoggerFactory.getLogger(ScanDescriptorForHostClassesStage.class);
29
30 @SuppressWarnings("unchecked")
31 public void execute(TransformContext context) throws PluginTransformationException {
32 XPath xpath = DocumentHelper.createXPath("//@class");
33 List<Attribute> attributes = xpath.selectNodes(context.getDescriptorDocument());
34 for (Attribute attr : attributes) {
35 String className = attr.getValue();
36
37 scanForHostComponents(context, className);
38
39 int dotpos = className.lastIndexOf(".");
40 if (dotpos > -1) {
41 String pkg = className.substring(0, dotpos);
42 String pkgPath = pkg.replace('.', '/') + '/';
43
44
45 if (context.getSystemExports().isExported(pkg)) {
46 if (context.getPluginArtifact().doesResourceExist(pkgPath)) {
47 if (isAtlassianDevMode())
48 log.warn("The plugin '{}' uses a package '{}' that is also exported by the application. "
49 + "It is highly recommended that the plugin use its own packages.",
50 context.getPluginArtifact(), pkg);
51 } else {
52 context.getExtraImports().add(pkg);
53 }
54 }
55 }
56 }
57 }
58
59 private void scanForHostComponents(TransformContext context, String className) {
60
61 if (className != null && className.contains(":")) {
62 return;
63 }
64
65 Map<Class<?>, HostComponentRegistration> hostComponentInterfaces = new LinkedHashMap<>();
66 for (HostComponentRegistration registration : context.getHostComponentRegistrations()) {
67 for (Class<?> cls : registration.getMainInterfaceClasses()) {
68 hostComponentInterfaces.put(cls, registration);
69 }
70 }
71
72 Class cls;
73 try {
74 cls = ClassLoaderUtils.loadClass(className, getClass());
75 } catch (ClassNotFoundException e) {
76
77 return;
78 }
79
80
81 for (Constructor ctor : cls.getConstructors()) {
82 for (Class<?> ctorParam : ctor.getParameterTypes()) {
83 if (hostComponentInterfaces.containsKey(ctorParam)) {
84 context.addRequiredHostComponent(hostComponentInterfaces.get(ctorParam));
85 }
86 }
87 }
88
89
90 for (Method method : cls.getMethods()) {
91 if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) {
92 if (hostComponentInterfaces.containsKey(method.getParameterTypes()[0])) {
93 context.addRequiredHostComponent(hostComponentInterfaces.get(method.getParameterTypes()[0]));
94 }
95 }
96 }
97 }
98 }