1 package com.atlassian.plugin.refimpl;
2
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9
10 import javax.servlet.ServletContext;
11
12 import org.apache.commons.lang.StringUtils;
13
14 import com.atlassian.plugin.DefaultModuleDescriptorFactory;
15 import com.atlassian.plugin.ModuleDescriptorFactory;
16 import com.atlassian.plugin.PluginAccessor;
17 import com.atlassian.plugin.PluginController;
18 import com.atlassian.plugin.PluginParseException;
19 import com.atlassian.plugin.event.PluginEventManager;
20 import com.atlassian.plugin.hostcontainer.HostContainer;
21 import com.atlassian.plugin.main.AtlassianPlugins;
22 import com.atlassian.plugin.main.PluginsConfiguration;
23 import com.atlassian.plugin.main.PluginsConfigurationBuilder;
24 import com.atlassian.plugin.osgi.container.OsgiContainerManager;
25 import com.atlassian.plugin.osgi.container.impl.DefaultPackageScannerConfiguration;
26 import com.atlassian.plugin.osgi.hostcomponents.ComponentRegistrar;
27 import com.atlassian.plugin.osgi.hostcomponents.HostComponentProvider;
28 import com.atlassian.plugin.refimpl.servlet.SimpleServletContextFactory;
29 import com.atlassian.plugin.refimpl.webresource.SimpleWebResourceIntegration;
30 import com.atlassian.plugin.servlet.ContentTypeResolver;
31 import com.atlassian.plugin.servlet.DefaultServletModuleManager;
32 import com.atlassian.plugin.servlet.DownloadStrategy;
33 import com.atlassian.plugin.servlet.PluginResourceDownload;
34 import com.atlassian.plugin.servlet.ServletModuleManager;
35 import com.atlassian.plugin.servlet.descriptors.ServletContextListenerModuleDescriptor;
36 import com.atlassian.plugin.servlet.descriptors.ServletContextParamModuleDescriptor;
37 import com.atlassian.plugin.servlet.descriptors.ServletFilterModuleDescriptor;
38 import com.atlassian.plugin.servlet.descriptors.ServletModuleDescriptor;
39 import com.atlassian.plugin.servlet.util.ServletContextHostContainerAccessor;
40 import com.atlassian.plugin.util.Assertions;
41 import com.atlassian.plugin.web.descriptors.DefaultWebItemModuleDescriptor;
42 import com.atlassian.plugin.webresource.PluginResourceLocator;
43 import com.atlassian.plugin.webresource.PluginResourceLocatorImpl;
44 import com.atlassian.plugin.webresource.WebResourceIntegration;
45 import com.atlassian.plugin.webresource.WebResourceManager;
46 import com.atlassian.plugin.webresource.WebResourceManagerImpl;
47 import com.atlassian.plugin.webresource.WebResourceModuleDescriptor;
48
49
50
51
52 public class ContainerManager
53 {
54 private final ServletModuleManager servletModuleManager;
55 private final SimpleWebResourceIntegration webResourceIntegration;
56 private final WebResourceManager webResourceManager;
57 private final OsgiContainerManager osgiContainerManager;
58 private final PluginAccessor pluginAccessor;
59 private final HostComponentProvider hostComponentProvider;
60 private final DefaultModuleDescriptorFactory moduleDescriptorFactory;
61 private final Map<Class<?>, Object> publicContainer;
62 private final AtlassianPlugins plugins;
63 private final HostContainer hostContainer;
64
65 private static ContainerManager instance;
66 private final List<DownloadStrategy> downloadStrategies;
67
68 public ContainerManager(final ServletContext servletContext)
69 {
70 instance = this;
71 webResourceIntegration = new SimpleWebResourceIntegration(servletContext);
72
73
74 final HostContainer delegatingHostContainer = new HostContainer()
75 {
76 public <T> T create(final Class<T> moduleClass) throws IllegalArgumentException
77 {
78 return hostContainer.create(moduleClass);
79 }
80
81 public <T> T getInstance(final Class<T> moduleClass)
82 {
83 return hostContainer.getInstance(moduleClass);
84 }
85 };
86 ServletContextHostContainerAccessor.setHostContainer(servletContext, delegatingHostContainer);
87
88 moduleDescriptorFactory = new DefaultModuleDescriptorFactory(delegatingHostContainer);
89
90 moduleDescriptorFactory.addModuleDescriptor("servlet", ServletModuleDescriptor.class);
91 moduleDescriptorFactory.addModuleDescriptor("servlet-filter", ServletFilterModuleDescriptor.class);
92 moduleDescriptorFactory.addModuleDescriptor("servlet-context-param", ServletContextParamModuleDescriptor.class);
93 moduleDescriptorFactory.addModuleDescriptor("servlet-context-listener", ServletContextListenerModuleDescriptor.class);
94 moduleDescriptorFactory.addModuleDescriptor("web-resource", WebResourceModuleDescriptor.class);
95 moduleDescriptorFactory.addModuleDescriptor("web-item", DefaultWebItemModuleDescriptor.class);
96
97 final DefaultPackageScannerConfiguration scannerConfig = new DefaultPackageScannerConfiguration();
98 final List<String> packageIncludes = new ArrayList<String>(scannerConfig.getPackageIncludes());
99 packageIncludes.add("org.bouncycastle*");
100 packageIncludes.add("org.dom4j");
101
102 scannerConfig.setPackageIncludes(packageIncludes);
103 hostComponentProvider = new SimpleHostComponentProvider();
104
105 final PluginsConfiguration config = new PluginsConfigurationBuilder()
106 .pluginDirectory(makeSureDirectoryExists(servletContext, "/WEB-INF/plugins"))
107 .moduleDescriptorFactory(moduleDescriptorFactory)
108 .packageScannerConfiguration(scannerConfig)
109 .hostComponentProvider(hostComponentProvider)
110 .frameworkBundlesDirectory(makeSureDirectoryExists(servletContext, "/WEB-INF/framework-bundles"))
111 .build();
112 plugins = new AtlassianPlugins(config);
113
114 final PluginEventManager pluginEventManager = plugins.getPluginEventManager();
115 osgiContainerManager = plugins.getOsgiContainerManager();
116
117 servletModuleManager = new DefaultServletModuleManager(pluginEventManager);
118 pluginAccessor = plugins.getPluginAccessor();
119
120 PluginResourceLocator pluginResourceLocator = new PluginResourceLocatorImpl(pluginAccessor, new SimpleServletContextFactory(servletContext));
121 PluginResourceDownload pluginDownloadStrategy = new PluginResourceDownload(pluginResourceLocator, new SimpleContentTypeResolver(), "UTF-8");
122
123 webResourceManager = new WebResourceManagerImpl(pluginResourceLocator, webResourceIntegration);
124
125 publicContainer = new HashMap<Class<?>, Object>();
126 publicContainer.put(PluginController.class, plugins.getPluginController());
127 publicContainer.put(PluginAccessor.class, pluginAccessor);
128 publicContainer.put(PluginEventManager.class, pluginEventManager);
129 publicContainer.put(ServletModuleManager.class, servletModuleManager);
130 publicContainer.put(WebResourceManager.class, webResourceManager);
131 publicContainer.put(Map.class, publicContainer);
132
133 hostContainer = new RefimplHostContainer(publicContainer, osgiContainerManager);
134
135 try
136 {
137 plugins.start();
138 }
139 catch (final PluginParseException e)
140 {
141 throw new RuntimeException(e);
142 }
143
144 downloadStrategies = new ArrayList<DownloadStrategy>();
145 downloadStrategies.add(pluginDownloadStrategy);
146 }
147
148 private File makeSureDirectoryExists(ServletContext servletContext, String relativePath)
149 {
150 final File dir = new File(servletContext.getRealPath(relativePath));
151 if (!dir.exists() && !dir.mkdirs())
152 {
153 throw new RuntimeException("Could not create directory <" + dir + ">");
154 }
155 return dir;
156 }
157
158 public static synchronized void setInstance(final ContainerManager mgr)
159 {
160 instance = mgr;
161 }
162
163 public static synchronized ContainerManager getInstance()
164 {
165 return instance;
166 }
167
168 public ServletModuleManager getServletModuleManager()
169 {
170 return servletModuleManager;
171 }
172
173 public OsgiContainerManager getOsgiContainerManager()
174 {
175 return osgiContainerManager;
176 }
177
178 public PluginAccessor getPluginAccessor()
179 {
180 return pluginAccessor;
181 }
182
183 public HostComponentProvider getHostComponentProvider()
184 {
185 return hostComponentProvider;
186 }
187
188 public ModuleDescriptorFactory getModuleDescriptorFactory()
189 {
190 return moduleDescriptorFactory;
191 }
192
193 public List<DownloadStrategy> getDownloadStrategies()
194 {
195 return downloadStrategies;
196 }
197
198 public WebResourceManager getWebResourceManager()
199 {
200 return webResourceManager;
201 }
202
203 public WebResourceIntegration getWebResourceIntegration()
204 {
205 return webResourceIntegration;
206 }
207
208 void shutdown()
209 {
210 plugins.stop();
211 }
212
213
214
215
216 private class SimpleContentTypeResolver implements ContentTypeResolver
217 {
218 private final Map<String, String> mimeTypes;
219
220 SimpleContentTypeResolver()
221 {
222 final Map<String, String> types = new HashMap<String, String>();
223 types.put("js", "application/x-javascript");
224 types.put("css", "text/css");
225 mimeTypes = Collections.unmodifiableMap(types);
226 }
227
228 public String getContentType(final String requestUrl)
229 {
230 final String extension = requestUrl.substring(requestUrl.lastIndexOf('.'));
231 return mimeTypes.get(extension);
232 }
233 }
234
235 private class SimpleHostComponentProvider implements HostComponentProvider
236 {
237 public void provide(final ComponentRegistrar componentRegistrar)
238 {
239 Assertions.notNull("publicContainer", publicContainer);
240 for (final Map.Entry<Class<?>, Object> entry : publicContainer.entrySet())
241 {
242 final String name = StringUtils.uncapitalize(entry.getKey().getSimpleName());
243 componentRegistrar.register(entry.getKey()).forInstance(entry.getValue()).withName(name);
244 }
245
246 }
247 }
248 }