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