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.factory.transform.model.ComponentImport;
7 import com.atlassian.plugin.util.PluginUtils;
8 import org.dom4j.Document;
9 import org.dom4j.Element;
10 import org.osgi.framework.ServiceReference;
11 import org.osgi.framework.Constants;
12 import org.slf4j.LoggerFactory;
13 import org.slf4j.Logger;
14
15
16
17
18
19
20 public class ComponentImportSpringStage implements TransformStage
21 {
22
23 private static final String SPRING_XML = "META-INF/spring/atlassian-plugins-component-imports.xml";
24 private static final String INITIALIZING_OSGI_SERVICE_LIFECYCLE_LISTENER = "initializingOsgiServiceLifecycleListener";
25
26 public static final String BEAN_SOURCE = "Component Import";
27
28 Logger log = LoggerFactory.getLogger(ComponentImportSpringStage.class);
29
30 public void execute(TransformContext context) throws PluginTransformationException
31 {
32 if (SpringHelper.shouldGenerateFile(context, SPRING_XML))
33 {
34 Document springDoc = SpringHelper.createSpringDocument();
35 Element root = springDoc.getRootElement();
36
37 ServiceReference[] serviceReferences = context.getOsgiContainerManager().getRegisteredServices();
38 for (ComponentImport comp: context.getComponentImports().values())
39 {
40 if (!PluginUtils.doesModuleElementApplyToApplication(comp.getSource(), context.getApplications(), context.getInstallationMode()))
41 {
42 continue;
43 }
44 Element osgiReference = root.addElement("osgi:reference");
45
46
47 context.trackBean(comp.getKey(), BEAN_SOURCE);
48
49 osgiReference.addAttribute("id", comp.getKey());
50
51 if (comp.getFilter() != null)
52 {
53 osgiReference.addAttribute("filter", comp.getFilter());
54 }
55
56 Element referenceListener = osgiReference.addElement("osgi:reference-listener");
57 referenceListener.addAttribute("ref", INITIALIZING_OSGI_SERVICE_LIFECYCLE_LISTENER);
58 referenceListener.addAttribute("bind-method", "bind");
59
60 Element interfaces = osgiReference.addElement("osgi:interfaces");
61 for (String infName : comp.getInterfaces())
62 {
63 validateInterface(infName, context.getPluginFile().getName(), serviceReferences);
64 context.getExtraImports().add(infName.substring(0, infName.lastIndexOf('.')));
65 Element e = interfaces.addElement("beans:value");
66 e.setText(infName);
67 }
68 }
69 if (root.elements().size() > 0)
70 {
71 Element osgiServiceLifecycleListener = root.addElement("beans:bean");
72 osgiServiceLifecycleListener.addAttribute("id", INITIALIZING_OSGI_SERVICE_LIFECYCLE_LISTENER);
73 osgiServiceLifecycleListener.addAttribute("class", "com.atlassian.plugin.osgi.bridge.external.InitializingOsgiServiceLifecycleListener");
74 context.getExtraImports().add("com.atlassian.plugin.osgi.bridge.external");
75
76 context.setShouldRequireSpring(true);
77 context.getFileOverrides().put(SPRING_XML, SpringHelper.documentToBytes(springDoc));
78 }
79 }
80 }
81
82 private void validateInterface(String interfaceName, String pluginName, ServiceReference[] serviceReferences)
83 {
84 if (log.isDebugEnabled())
85 {
86 boolean found = false;
87 outer:
88 for (ServiceReference ref : serviceReferences)
89 {
90
91 for (String clazz : (String[]) ref.getProperty(Constants.OBJECTCLASS))
92 {
93 if (interfaceName.equals(clazz))
94 {
95 found = true;
96 break outer;
97 }
98 }
99 }
100 if (!found)
101 {
102 log.debug("Couldn't confirm that '" + interfaceName + "' (used as a <component-import> in the plugin with name '" + pluginName +
103 "') is a public component in the product's OSGi exports. If this is an interface you expect to be" +
104 " provided from the product, double check the spelling of '" + interfaceName + "'; if this class" +
105 " is supposed to come from another plugin, you can probably ignore this warning.");
106 }
107 }
108
109 }
110 }