1 package com.atlassian.plugin.osgi.factory.transform.stage;
2
3 import com.atlassian.plugin.osgi.factory.transform.TransformStage;
4 import com.atlassian.plugin.osgi.factory.transform.TransformContext;
5 import com.atlassian.plugin.osgi.factory.transform.PluginTransformationException;
6 import static com.atlassian.plugin.util.validation.ValidationPattern.createPattern;
7 import static com.atlassian.plugin.util.validation.ValidationPattern.test;
8 import com.atlassian.plugin.util.validation.ValidationPattern;
9 import com.atlassian.plugin.util.PluginUtils;
10 import org.dom4j.Document;
11 import org.dom4j.Element;
12
13 import java.util.List;
14 import java.util.ArrayList;
15
16
17
18
19
20
21 public class ComponentSpringStage implements TransformStage
22 {
23
24 private static final String SPRING_XML = "META-INF/spring/atlassian-plugins-components.xml";
25
26 public void execute(TransformContext context) throws PluginTransformationException
27 {
28 if (SpringHelper.shouldGenerateFile(context, SPRING_XML))
29 {
30 Document springDoc = SpringHelper.createSpringDocument();
31 Element root = springDoc.getRootElement();
32 List<Element> elements = context.getDescriptorDocument().getRootElement().elements("component");
33
34 ValidationPattern validation = createPattern().
35 rule(
36 test("@key").withError("The key is required"),
37 test("@class").withError("The class is required"),
38 test("not(@public) or interface or @interface").withError("Interfaces must be declared for public components"),
39 test("not(service-properties) or count(service-properties/entry[@key and @value]) > 0")
40 .withError("The service-properties element must contain at least one entry element with key and value attributes"));
41
42 for (Element component : elements)
43 {
44 if (!PluginUtils.doesModuleElementApplyToApplication(component, context.getApplicationKeys()))
45 {
46 continue;
47 }
48 validation.evaluate(component);
49
50 Element bean = root.addElement("beans:bean");
51 bean.addAttribute("id", component.attributeValue("key"));
52 bean.addAttribute("alias", component.attributeValue("alias"));
53 bean.addAttribute("class", component.attributeValue("class"));
54 if ("true".equalsIgnoreCase(component.attributeValue("public")))
55 {
56 Element osgiService = root.addElement("osgi:service");
57 osgiService.addAttribute("id", component.attributeValue("key") + "_osgiService");
58 osgiService.addAttribute("ref", component.attributeValue("key"));
59
60 List<String> interfaceNames = new ArrayList<String>();
61 List<Element> compInterfaces = component.elements("interface");
62 for (Element inf : compInterfaces)
63 {
64 interfaceNames.add(inf.getTextTrim());
65 }
66 if (component.attributeValue("interface") != null)
67 {
68 interfaceNames.add(component.attributeValue("interface"));
69 }
70
71 Element interfaces = osgiService.addElement("osgi:interfaces");
72 for (String name : interfaceNames)
73 {
74 ensureExported(name, context);
75 Element e = interfaces.addElement("beans:value");
76 e.setText(name);
77 }
78
79 Element svcprops = component.element("service-properties");
80 if (svcprops != null)
81 {
82 Element targetSvcprops = osgiService.addElement("osgi:service-properties");
83 for (Element prop : new ArrayList<Element>(svcprops.elements("entry")))
84 {
85 Element e = targetSvcprops.addElement("beans:entry");
86 e.addAttribute("key", prop.attributeValue("key"));
87 e.addAttribute("value", prop.attributeValue("value"));
88 }
89 }
90 }
91 }
92 if (root.elements().size() > 0)
93 {
94 context.setShouldRequireSpring(true);
95 context.getFileOverrides().put(SPRING_XML, SpringHelper.documentToBytes(springDoc));
96 }
97 }
98 }
99
100 void ensureExported(String className, TransformContext context)
101 {
102 String pkg = className.substring(0, className.lastIndexOf('.'));
103 if (!context.getExtraExports().contains(pkg))
104 {
105 String fileName = className.replace('.','/') + ".class";
106
107 if (context.getPluginArtifact().doesResourceExist(fileName))
108 {
109 context.getExtraExports().add(pkg);
110 }
111 }
112 }
113
114 }