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 {
24 private static Logger log = LoggerFactory.getLogger(DefaultModuleDescriptorFactory.class);
25
26 private final Map<String, Class<? extends ModuleDescriptor>> moduleDescriptorClasses = CopyOnWriteMap.<String, Class<? extends ModuleDescriptor>> builder().stableViews()
27 .newHashMap();
28 private final List<String> permittedModuleKeys = new ArrayList<String>();
29 private final HostContainer hostContainer;
30
31
32
33
34
35
36 @Deprecated
37 public DefaultModuleDescriptorFactory()
38 {
39 this(new DefaultHostContainer());
40 }
41
42
43
44
45
46
47
48
49
50 public DefaultModuleDescriptorFactory(final HostContainer hostContainer)
51 {
52 this.hostContainer = hostContainer;
53 }
54
55 public Class<? extends ModuleDescriptor> getModuleDescriptorClass(final String type)
56 {
57 return moduleDescriptorClasses.get(type);
58 }
59
60 public ModuleDescriptor<?> getModuleDescriptor(final String type) throws PluginParseException, IllegalAccessException, InstantiationException, ClassNotFoundException
61 {
62 if (shouldSkipModuleOfType(type))
63 {
64 return null;
65 }
66
67 final Class<? extends ModuleDescriptor> moduleDescriptorClazz = getModuleDescriptorClass(type);
68
69 if (moduleDescriptorClazz == null)
70 {
71 throw new PluginParseException("Cannot find ModuleDescriptor class for plugin of type '" + type + "'.");
72 }
73
74 return hostContainer.create(moduleDescriptorClazz);
75 }
76
77 protected boolean shouldSkipModuleOfType(final String type)
78 {
79 synchronized (permittedModuleKeys)
80 {
81 return !permittedModuleKeys.isEmpty() && !permittedModuleKeys.contains(type);
82 }
83 }
84
85 @SuppressWarnings("unused")
86 public void setModuleDescriptors(final Map<String, String> moduleDescriptorClassNames)
87 {
88 for (final Entry<String, String> entry : moduleDescriptorClassNames.entrySet())
89 {
90 final Class<ModuleDescriptor<?>> descriptorClass = getClassFromEntry(entry);
91 if (descriptorClass != null)
92 {
93 addModuleDescriptor(entry.getKey(), descriptorClass);
94 }
95 }
96 }
97
98 private <D extends ModuleDescriptor<?>> Class<D> getClassFromEntry(final Map.Entry<String, String> entry)
99 {
100 if (shouldSkipModuleOfType(entry.getKey()))
101 {
102 return null;
103 }
104
105 try
106 {
107 final Class<D> descriptorClass = ClassLoaderUtils.loadClass(entry.getValue(), getClass());
108
109 if (!ModuleDescriptor.class.isAssignableFrom(descriptorClass))
110 {
111 log.error("Configured plugin module descriptor class " + entry.getValue() + " does not inherit from ModuleDescriptor");
112 return null;
113 }
114 return descriptorClass;
115 }
116 catch (final ClassNotFoundException e)
117 {
118 log.error("Unable to add configured plugin module descriptor " + entry.getKey() + ". Class not found: " + entry.getValue());
119 return null;
120 }
121 }
122
123 public boolean hasModuleDescriptor(final String type)
124 {
125 return moduleDescriptorClasses.containsKey(type);
126 }
127
128 public void addModuleDescriptor(final String type, final Class<? extends ModuleDescriptor> moduleDescriptorClass)
129 {
130 moduleDescriptorClasses.put(type, moduleDescriptorClass);
131 }
132
133 public void removeModuleDescriptorForType(final String type)
134 {
135 moduleDescriptorClasses.remove(type);
136 }
137
138 protected final Map<String, Class<? extends ModuleDescriptor>> getDescriptorClassesMap()
139 {
140 return unmodifiableMap(moduleDescriptorClasses);
141 }
142
143
144
145
146
147
148
149
150 public void setPermittedModuleKeys(List<String> permittedModuleKeys)
151 {
152 if (permittedModuleKeys == null)
153 {
154 permittedModuleKeys = Collections.emptyList();
155 }
156
157 synchronized (this.permittedModuleKeys)
158 {
159
160 this.permittedModuleKeys.clear();
161 this.permittedModuleKeys.addAll(permittedModuleKeys);
162 }
163 }
164 }