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      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                  // make sure the new bean id is not already in use.
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 }