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