1 package com.atlassian.plugin.osgi.factory;
2
3 import com.atlassian.plugin.ModuleDescriptor;
4 import com.atlassian.plugin.PluginState;
5 import com.atlassian.plugin.descriptors.UnrecognisedModuleDescriptor;
6 import com.atlassian.plugin.event.PluginEventManager;
7 import com.atlassian.plugin.event.events.PluginModuleAvailableEvent;
8 import com.atlassian.plugin.event.events.PluginModuleUnavailableEvent;
9 import com.atlassian.plugin.osgi.external.ListableModuleDescriptorFactory;
10 import org.dom4j.Element;
11 import org.osgi.framework.Bundle;
12 import org.osgi.framework.ServiceReference;
13 import org.osgi.util.tracker.ServiceTrackerCustomizer;
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22
23
24
25
26
27
28
29 class UnrecognizedModuleDescriptorServiceTrackerCustomizer implements ServiceTrackerCustomizer {
30 private static final Logger log = LoggerFactory.getLogger(UnrecognizedModuleDescriptorServiceTrackerCustomizer.class);
31
32 private final Bundle bundle;
33 private final OsgiPlugin plugin;
34 private final PluginEventManager pluginEventManager;
35
36 public UnrecognizedModuleDescriptorServiceTrackerCustomizer(OsgiPlugin plugin, PluginEventManager pluginEventManager) {
37 this.plugin = checkNotNull(plugin);
38 this.bundle = checkNotNull(plugin.getBundle());
39 this.pluginEventManager = checkNotNull(pluginEventManager);
40 }
41
42
43
44
45
46 public Object addingService(final ServiceReference serviceReference) {
47 final ListableModuleDescriptorFactory factory = (ListableModuleDescriptorFactory) bundle.getBundleContext().getService(serviceReference);
48
49
50
51 if (canFactoryResolveUnrecognizedDescriptor(factory) || isFactoryInUse(factory)) {
52 return factory;
53 } else {
54
55
56 bundle.getBundleContext().ungetService(serviceReference);
57 return null;
58 }
59 }
60
61
62
63
64
65
66
67 private boolean canFactoryResolveUnrecognizedDescriptor(ListableModuleDescriptorFactory factory) {
68 boolean usedFactory = false;
69 for (final UnrecognisedModuleDescriptor unrecognised : getModuleDescriptorsByDescriptorClass(UnrecognisedModuleDescriptor.class)) {
70 final Element source = plugin.getModuleElements().get(unrecognised.getKey());
71 if ((source != null) && factory.hasModuleDescriptor(source.getName())) {
72 usedFactory = true;
73 try {
74 final ModuleDescriptor<?> descriptor = factory.getModuleDescriptor(source.getName());
75 descriptor.init(unrecognised.getPlugin(), source);
76 plugin.addModuleDescriptor(descriptor);
77 log.info("Turned unrecognized plugin module {} into module {}", descriptor.getCompleteKey(), descriptor);
78 pluginEventManager.broadcast(new PluginModuleAvailableEvent(descriptor));
79 } catch (final Exception e) {
80 log.error("Unable to transform {} into actual plugin module using factory {}", new Object[]{unrecognised.getCompleteKey(), factory, e});
81 unrecognised.setErrorText(e.getMessage());
82 }
83 }
84 }
85 return usedFactory;
86 }
87
88
89
90
91
92
93
94 private boolean isFactoryInUse(ListableModuleDescriptorFactory factory) {
95 for (ModuleDescriptor<?> descriptor : plugin.getModuleDescriptors()) {
96 for (Class<? extends ModuleDescriptor> descriptorClass : factory.getModuleDescriptorClasses()) {
97 if (descriptorClass == descriptor.getClass()) {
98 return true;
99 }
100 }
101 }
102 return false;
103 }
104
105 public void modifiedService(final ServiceReference serviceReference, final Object o) {
106
107 }
108
109
110
111
112
113 public void removedService(final ServiceReference serviceReference, final Object o) {
114 final ListableModuleDescriptorFactory factory = (ListableModuleDescriptorFactory) o;
115 for (final Class<? extends ModuleDescriptor> moduleDescriptorClass : factory.getModuleDescriptorClasses()) {
116 for (final ModuleDescriptor<?> descriptor : getModuleDescriptorsByDescriptorClass(moduleDescriptorClass)) {
117 if (plugin.getPluginState() == PluginState.ENABLED) {
118 pluginEventManager.broadcast(new PluginModuleUnavailableEvent(descriptor));
119 log.info("Removed plugin module {} as its factory was uninstalled", descriptor.getCompleteKey());
120 }
121 plugin.clearModuleDescriptor(descriptor.getKey());
122
123 if (plugin.isFrameworkShuttingDown()) {
124 continue;
125 }
126 final UnrecognisedModuleDescriptor unrecognisedModuleDescriptor = new UnrecognisedModuleDescriptor();
127 final Element source = plugin.getModuleElements().get(descriptor.getKey());
128 if (source != null) {
129 unrecognisedModuleDescriptor.init(plugin, source);
130 unrecognisedModuleDescriptor.setErrorText(UnrecognisedModuleDescriptorFallbackFactory.DESCRIPTOR_TEXT);
131 plugin.addModuleDescriptor(unrecognisedModuleDescriptor);
132
133 if (plugin.getPluginState() == PluginState.ENABLED) {
134 pluginEventManager.broadcast(new PluginModuleAvailableEvent(unrecognisedModuleDescriptor));
135 }
136 }
137 }
138 }
139 }
140
141
142
143
144
145
146 <T extends ModuleDescriptor<?>> List<T> getModuleDescriptorsByDescriptorClass(final Class<T> descriptor) {
147 final List<T> result = new ArrayList<T>();
148
149 for (final ModuleDescriptor<?> moduleDescriptor : plugin.getModuleDescriptors()) {
150 if (descriptor.isAssignableFrom(moduleDescriptor.getClass())) {
151 result.add(descriptor.cast(moduleDescriptor));
152 }
153 }
154 return result;
155 }
156 }