View Javadoc
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.Constants;
11  import org.osgi.framework.ServiceReference;
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  
15  /**
16   * Transforms component imports into a Spring XML file
17   *
18   * @since 2.2.0
19   */
20  public class ComponentImportSpringStage implements TransformStage {
21      /**
22       * Path of generated Spring XML file
23       */
24      private static final String SPRING_XML = "META-INF/spring/atlassian-plugins-component-imports.xml";
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          if (SpringHelper.shouldGenerateFile(context, SPRING_XML)) {
32              Document springDoc = SpringHelper.createSpringDocument();
33              Element root = springDoc.getRootElement();
34  
35              ServiceReference[] serviceReferences = context.getOsgiContainerManager().getRegisteredServices();
36              for (ComponentImport comp : context.getComponentImports().values()) {
37                  if (!PluginUtils.doesModuleElementApplyToApplication(comp.getSource(), context.getApplications(), context.getInstallationMode())) {
38                      continue;
39                  }
40                  Element osgiReference = root.addElement("osgi:reference");
41  
42                  // make sure the new bean id is not already in use.
43                  context.trackBean(comp.getKey(), BEAN_SOURCE);
44  
45                  osgiReference.addAttribute("id", comp.getKey());
46  
47                  if (comp.getFilter() != null) {
48                      osgiReference.addAttribute("filter", comp.getFilter());
49                  }
50  
51                  Element interfaces = osgiReference.addElement("osgi:interfaces");
52                  for (String infName : comp.getInterfaces()) {
53                      validateInterface(infName, context.getPluginFile().getName(), serviceReferences);
54                      context.getExtraImports().add(infName.substring(0, infName.lastIndexOf('.')));
55                      Element e = interfaces.addElement("beans:value");
56                      e.setText(infName);
57                  }
58              }
59              if (root.elements().size() > 0) {
60                  context.setShouldRequireSpring(true);
61                  context.getFileOverrides().put(SPRING_XML, SpringHelper.documentToBytes(springDoc));
62              }
63          }
64      }
65  
66      private void validateInterface(String interfaceName, String pluginName, ServiceReference[] serviceReferences) {
67          if (log.isDebugEnabled()) {
68              boolean found = false;
69              outer:
70              for (ServiceReference ref : serviceReferences) {
71  
72                  for (String clazz : (String[]) ref.getProperty(Constants.OBJECTCLASS)) {
73                      if (interfaceName.equals(clazz)) {
74                          found = true;
75                          break outer;
76                      }
77                  }
78              }
79              if (!found) {
80                  log.debug("Couldn't confirm that '{}' (used as a <component-import> in the plugin with name '{}')" +
81                          " is a public component in the product's OSGi exports. If this is an interface you expect to" +
82                          " be provided from the product, double check the spelling of '{}'; if this class" +
83                          " is supposed to come from another plugin, you can probably ignore this warning.",
84                          interfaceName, pluginName, interfaceName);
85              }
86          }
87  
88      }
89  }