1 package com.atlassian.plugin.loaders;
2
3 import static com.atlassian.plugin.util.Assertions.notNull;
4
5 import com.atlassian.plugin.ModuleDescriptorFactory;
6 import com.atlassian.plugin.Plugin;
7 import com.atlassian.plugin.PluginException;
8 import com.atlassian.plugin.PluginParseException;
9 import com.atlassian.plugin.impl.StaticPlugin;
10 import com.atlassian.plugin.impl.UnloadablePlugin;
11 import com.atlassian.plugin.impl.UnloadablePluginFactory;
12 import com.atlassian.plugin.parsers.DescriptorParser;
13 import com.atlassian.plugin.parsers.DescriptorParserFactory;
14 import com.atlassian.plugin.parsers.XmlDescriptorParserFactory;
15 import com.atlassian.plugin.util.ClassLoaderUtils;
16
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.net.URL;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.concurrent.atomic.AtomicReference;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class SinglePluginLoader implements PluginLoader
38 {
39 protected Collection<Plugin> plugins;
40
41
42
43
44 private final String resource;
45
46
47
48
49 private final URL url;
50
51 private final DescriptorParserFactory descriptorParserFactory = new XmlDescriptorParserFactory();
52
53
54
55
56 private final AtomicReference<InputStream> inputStreamRef;
57
58
59 public SinglePluginLoader(final String resource)
60 {
61 this.resource = notNull("resource", resource);
62 url = null;
63 inputStreamRef = new AtomicReference<InputStream>(null);
64 }
65
66 public SinglePluginLoader(final URL url)
67 {
68 this.url = notNull("url", url);
69 resource = null;
70 inputStreamRef = new AtomicReference<InputStream>(null);
71 }
72
73
74
75
76 public SinglePluginLoader(final InputStream is)
77 {
78 inputStreamRef = new AtomicReference<InputStream>(notNull("inputStream", is));
79 resource = null;
80 url = null;
81 }
82
83 public Collection<Plugin> loadAllPlugins(final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
84 {
85 if (plugins == null)
86 {
87 plugins = Collections.singleton(loadPlugin(moduleDescriptorFactory));
88 }
89 return plugins;
90 }
91
92 public boolean supportsRemoval()
93 {
94 return false;
95 }
96
97 public boolean supportsAddition()
98 {
99 return false;
100 }
101
102 public Collection<Plugin> addFoundPlugins(final ModuleDescriptorFactory moduleDescriptorFactory)
103 {
104 throw new UnsupportedOperationException("This PluginLoader does not support addition.");
105 }
106
107 public void removePlugin(final Plugin plugin) throws PluginException
108 {
109 throw new PluginException("This PluginLoader does not support removal.");
110 }
111
112 protected Plugin loadPlugin(final ModuleDescriptorFactory moduleDescriptorFactory) throws PluginParseException
113 {
114 final InputStream source = getSource();
115 if (source == null)
116 {
117 throw new PluginParseException("Invalid resource or inputstream specified to load plugins from.");
118 }
119
120 Plugin plugin;
121 try
122 {
123 final DescriptorParser parser = descriptorParserFactory.getInstance(source);
124 plugin = parser.configurePlugin(moduleDescriptorFactory, getNewPlugin());
125 if (plugin.getPluginsVersion() == 2)
126 {
127 UnloadablePlugin unloadablePlugin = UnloadablePluginFactory.createUnloadablePlugin(plugin);
128 final StringBuilder errorText = new StringBuilder("OSGi plugins cannot be deployed via the classpath, which is usually WEB-INF/lib.");
129 if (resource != null) {
130 errorText.append(" Resource is: " + resource);
131 }
132 if (url != null) {
133 errorText.append(" URL is: " + url);
134 }
135 unloadablePlugin.setErrorText(errorText.toString());
136 plugin = unloadablePlugin;
137 }
138 else if (parser.isSystemPlugin())
139 {
140 plugin.setSystemPlugin(true);
141 }
142 }
143 catch (final PluginParseException e)
144 {
145 throw new PluginParseException("Unable to load plugin resource: " + resource + " - " + e.getMessage(), e);
146 }
147
148 return plugin;
149 }
150
151 protected StaticPlugin getNewPlugin()
152 {
153 return new StaticPlugin();
154 }
155
156 protected InputStream getSource()
157 {
158 if (resource != null)
159 {
160 return ClassLoaderUtils.getResourceAsStream(resource, this.getClass());
161 }
162
163 if (url != null)
164 {
165 try
166 {
167 return url.openConnection().getInputStream();
168 }
169 catch (IOException e)
170 {
171 throw new PluginParseException(e);
172 }
173 }
174
175 final InputStream inputStream = inputStreamRef.getAndSet(null);
176 if (inputStream != null)
177 {
178 return inputStream;
179 }
180 throw new IllegalStateException("No defined method for getting an input stream.");
181 }
182 }