1 package com.atlassian.plugin;
2
3 import com.atlassian.plugin.hostcontainer.DefaultHostContainer;
4 import com.atlassian.plugin.hostcontainer.HostContainer;
5 import com.atlassian.plugin.util.ClassLoaderUtils;
6 import com.atlassian.util.concurrent.CopyOnWriteMap;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Map.Entry;
15
16 import static java.util.Collections.unmodifiableMap;
17
18
19
20
21
22 public class DefaultModuleDescriptorFactory implements ModuleDescriptorFactory {
23 private static Logger log = LoggerFactory.getLogger(DefaultModuleDescriptorFactory.class);
24
25 private final Map<String, Class<? extends ModuleDescriptor>> moduleDescriptorClasses = CopyOnWriteMap.<String, Class<? extends ModuleDescriptor>>builder().stableViews()
26 .newHashMap();
27 private final List<String> permittedModuleKeys = new ArrayList<String>();
28 private final HostContainer hostContainer;
29
30
31
32
33
34
35 @Deprecated
36 public DefaultModuleDescriptorFactory() {
37 this(new DefaultHostContainer());
38 }
39
40
41
42
43
44
45
46
47
48 public DefaultModuleDescriptorFactory(final HostContainer hostContainer) {
49 this.hostContainer = hostContainer;
50 }
51
52 public Class<? extends ModuleDescriptor> getModuleDescriptorClass(final String type) {
53 return moduleDescriptorClasses.get(type);
54 }
55
56 public ModuleDescriptor<?> getModuleDescriptor(final String type) throws PluginParseException, IllegalAccessException, InstantiationException, ClassNotFoundException {
57 if (shouldSkipModuleOfType(type)) {
58 return null;
59 }
60
61 final Class<? extends ModuleDescriptor> moduleDescriptorClazz = getModuleDescriptorClass(type);
62
63 if (moduleDescriptorClazz == null) {
64 throw new PluginParseException("Cannot find ModuleDescriptor class for plugin of type '" + type + "'.");
65 }
66
67 return hostContainer.create(moduleDescriptorClazz);
68 }
69
70 protected boolean shouldSkipModuleOfType(final String type) {
71 synchronized (permittedModuleKeys) {
72 return !permittedModuleKeys.isEmpty() && !permittedModuleKeys.contains(type);
73 }
74 }
75
76 @SuppressWarnings("unused")
77 public void setModuleDescriptors(final Map<String, String> moduleDescriptorClassNames) {
78 for (final Entry<String, String> entry : moduleDescriptorClassNames.entrySet()) {
79 final Class<ModuleDescriptor<?>> descriptorClass = getClassFromEntry(entry);
80 if (descriptorClass != null) {
81 addModuleDescriptor(entry.getKey(), descriptorClass);
82 }
83 }
84 }
85
86 private <D extends ModuleDescriptor<?>> Class<D> getClassFromEntry(final Map.Entry<String, String> entry) {
87 if (shouldSkipModuleOfType(entry.getKey())) {
88 return null;
89 }
90
91 try {
92 final Class<D> descriptorClass = ClassLoaderUtils.loadClass(entry.getValue(), getClass());
93
94 if (!ModuleDescriptor.class.isAssignableFrom(descriptorClass)) {
95 log.error("Configured plugin module descriptor class " + entry.getValue() + " does not inherit from ModuleDescriptor");
96 return null;
97 }
98 return descriptorClass;
99 } catch (final ClassNotFoundException e) {
100 log.error("Unable to add configured plugin module descriptor " + entry.getKey() + ". Class not found: " + entry.getValue());
101 return null;
102 }
103 }
104
105 public boolean hasModuleDescriptor(final String type) {
106 return moduleDescriptorClasses.containsKey(type);
107 }
108
109 public void addModuleDescriptor(final String type, final Class<? extends ModuleDescriptor> moduleDescriptorClass) {
110 moduleDescriptorClasses.put(type, moduleDescriptorClass);
111 }
112
113 public void removeModuleDescriptorForType(final String type) {
114 moduleDescriptorClasses.remove(type);
115 }
116
117 protected final Map<String, Class<? extends ModuleDescriptor>> getDescriptorClassesMap() {
118 return unmodifiableMap(moduleDescriptorClasses);
119 }
120
121
122
123
124
125
126
127
128 public void setPermittedModuleKeys(List<String> permittedModuleKeys) {
129 if (permittedModuleKeys == null) {
130 permittedModuleKeys = Collections.emptyList();
131 }
132
133 synchronized (this.permittedModuleKeys) {
134
135 this.permittedModuleKeys.clear();
136 this.permittedModuleKeys.addAll(permittedModuleKeys);
137 }
138 }
139 }