1 package com.atlassian.plugin.webresource;
2
3 import static com.atlassian.plugin.servlet.AbstractFileServerServlet.PATH_SEPARATOR;
4 import static com.atlassian.plugin.servlet.AbstractFileServerServlet.SERVLET_PATH;
5 import static com.google.common.collect.ImmutableList.copyOf;
6 import static com.google.common.collect.Iterables.any;
7
8 import com.atlassian.plugin.Plugin;
9 import com.atlassian.plugin.servlet.DownloadException;
10 import com.atlassian.plugin.servlet.DownloadableResource;
11
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import com.google.common.base.Predicate;
16 import com.google.common.collect.ImmutableMap;
17 import com.google.common.collect.Iterables;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URLEncoder;
23 import java.util.Collections;
24 import java.util.Map;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29
30
31
32
33
34
35
36
37
38
39 public class BatchPluginResource implements DownloadableResource, PluginResource, BatchResource
40 {
41 private static final Logger log = LoggerFactory.getLogger(BatchPluginResource.class);
42
43
44
45
46 static final String URL_PREFIX = PATH_SEPARATOR + SERVLET_PATH + PATH_SEPARATOR + "batch";
47
48 private final String type;
49 private final String moduleCompleteKey;
50 private final Map<String, String> params;
51 private final String resourceName;
52 private final Iterable<DownloadableResource> resources;
53
54
55
56
57
58
59
60
61
62
63 public BatchPluginResource(final String moduleCompleteKey, final String type, final Map<String, String> params)
64 {
65 this(moduleCompleteKey + "." + type, moduleCompleteKey, type, params, Collections.<DownloadableResource> emptyList());
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79 public BatchPluginResource(final String moduleCompleteKey, final String type, final Map<String, String> params, final Iterable<DownloadableResource> resources)
80 {
81 this(moduleCompleteKey + "." + type, moduleCompleteKey, type, params, resources);
82 }
83
84
85
86
87
88
89
90
91
92
93 BatchPluginResource(final String resourceName, final String moduleCompleteKey, final String type, final Map<String, String> params, final Iterable<DownloadableResource> resources)
94 {
95 this.resourceName = resourceName;
96 this.moduleCompleteKey = moduleCompleteKey;
97 this.type = type;
98 this.params = ImmutableMap.copyOf(params);
99 this.resources = copyOf(resources);
100 }
101
102
103
104
105 public boolean isEmpty()
106 {
107 return Iterables.isEmpty(resources);
108 }
109
110 public boolean isResourceModified(final HttpServletRequest request, final HttpServletResponse response)
111 {
112 return any(resources, new Predicate<DownloadableResource>()
113 {
114 public boolean apply(final DownloadableResource resource)
115 {
116 return resource.isResourceModified(request, response);
117 }
118 });
119 }
120
121 public void serveResource(final HttpServletRequest request, final HttpServletResponse response) throws DownloadException
122 {
123 if (log.isDebugEnabled())
124 {
125 log.debug("Start to serve batch " + toString());
126 }
127 for (final DownloadableResource resource : resources)
128 {
129 resource.serveResource(request, response);
130 writeNewLine(response);
131 }
132 }
133
134 public void streamResource(final OutputStream out) throws DownloadException
135 {
136 for (final DownloadableResource resource : resources)
137 {
138 resource.streamResource(out);
139 writeNewLine(out);
140 }
141 }
142
143 public String getContentType()
144 {
145 final String contentType = params.get("content-type");
146 if (contentType != null)
147 {
148 return contentType;
149 }
150 return null;
151 }
152
153
154
155
156
157
158
159
160
161
162
163 public String getUrl()
164 {
165 final StringBuilder sb = new StringBuilder();
166 sb.append(URL_PREFIX).append(PATH_SEPARATOR).append(moduleCompleteKey).append(PATH_SEPARATOR).append(resourceName);
167 addParamsToUrl(sb, params);
168 return sb.toString();
169 }
170
171 protected void addParamsToUrl(final StringBuilder sb, final Map<String, String> params)
172 {
173 if (params.size() > 0)
174 {
175 sb.append("?");
176 int count = 0;
177
178 for (final Map.Entry<String, String> entry : params.entrySet())
179 {
180 try
181 {
182 sb.append(URLEncoder.encode(entry.getKey(), "UTF-8")).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
183
184 if (++count < params.size())
185 {
186 sb.append("&");
187 }
188 }
189 catch (final UnsupportedEncodingException e)
190 {
191 log.error("Could not encode parameter to url for [" + entry.getKey() + "] with value [" + entry.getValue() + "]", e);
192 }
193 }
194 }
195 }
196
197 public String getResourceName()
198 {
199 return resourceName;
200 }
201
202 public Map<String, String> getParams()
203 {
204 return params;
205 }
206
207 public String getVersion(final WebResourceIntegration integration)
208 {
209 final Plugin plugin = integration.getPluginAccessor().getEnabledPluginModule(getModuleCompleteKey()).getPlugin();
210 return plugin.getPluginInformation().getVersion();
211 }
212
213 public String getModuleCompleteKey()
214 {
215 return moduleCompleteKey;
216 }
217
218 public boolean isCacheSupported()
219 {
220 return !"false".equals(params.get("cache"));
221 }
222
223 public String getType()
224 {
225 return type;
226 }
227
228 @Override
229 public boolean equals(final Object o)
230 {
231 if (this == o)
232 {
233 return true;
234 }
235 if ((o == null) || (getClass() != o.getClass()))
236 {
237 return false;
238 }
239
240 final BatchPluginResource that = (BatchPluginResource) o;
241
242 if (moduleCompleteKey != null ? !moduleCompleteKey.equals(that.moduleCompleteKey) : that.moduleCompleteKey != null)
243 {
244 return false;
245 }
246 if (params != null ? !params.equals(that.params) : that.params != null)
247 {
248 return false;
249 }
250 if (type != null ? !type.equals(that.type) : that.type != null)
251 {
252 return false;
253 }
254
255 return true;
256 }
257
258 @Override
259 public int hashCode()
260 {
261 int result;
262 result = (type != null ? type.hashCode() : 0);
263 result = 31 * result + (moduleCompleteKey != null ? moduleCompleteKey.hashCode() : 0);
264 result = 31 * result + (params != null ? params.hashCode() : 0);
265 return result;
266 }
267
268 @Override
269 public String toString()
270 {
271 return "[moduleCompleteKey=" + moduleCompleteKey + ", type=" + type + ", params=" + params + "]";
272 }
273
274
275
276
277
278
279
280
281
282 private static void writeNewLine(final HttpServletResponse response) throws DownloadException
283 {
284 try
285 {
286 writeNewLine(response.getOutputStream());
287 }
288 catch (final IOException e)
289 {
290 throw new DownloadException(e);
291 }
292 }
293
294 private static void writeNewLine(final OutputStream out) throws DownloadException
295 {
296 try
297 {
298 out.write('\n');
299 }
300 catch (final IOException e)
301 {
302 throw new DownloadException(e);
303 }
304 }
305 }