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