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