1 package com.atlassian.plugin.webresource;
2
3 import com.atlassian.plugin.cache.filecache.FileCacheStreamProvider;
4 import com.atlassian.plugin.servlet.DownloadException;
5 import com.atlassian.plugin.servlet.DownloadableResource;
6 import com.atlassian.plugin.webresource.cache.CacheHandle;
7 import com.google.common.base.Predicate;
8 import com.google.common.collect.ImmutableMap;
9 import com.google.common.collect.Iterables;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.util.Map;
18
19 import static com.google.common.collect.Iterables.any;
20
21
22
23
24
25
26 public abstract class AbstractBatchDownloadableResource implements DownloadableResource
27 {
28 private static final Logger log = LoggerFactory.getLogger(AbstractBatchDownloadableResource.class);
29
30 private static final ResourceContentAnnotator[] DEFAULT_ANNOTATORS = new ResourceContentAnnotator[] {
31 new NewlineResourceContentAnnotator()
32 };
33
34 private static final ResourceContentAnnotator[] JS_WRAP_ANNOTATORS = new ResourceContentAnnotator[] {
35 new NewlineResourceContentAnnotator(), new TryCatchJsResourceContentAnnotator()
36 };
37
38 private final String type;
39 private final Map<String, String> params;
40 private final Iterable<DownloadableResource> resources;
41 private final CacheHandle cacher;
42 private final ResourceContentAnnotator[] resourceContentAnnotators;
43
44
45
46
47
48
49
50
51 AbstractBatchDownloadableResource(final String type, final Map<String, String> params,
52 final Iterable<DownloadableResource> resources,
53 CacheHandle cacher)
54 {
55 this.type = type;
56 this.params = ImmutableMap.copyOf(params);
57 this.resources = resources;
58 this.cacher = cacher;
59 this.resourceContentAnnotators = getAnnotators();
60 }
61
62
63
64
65 public boolean isEmpty()
66 {
67 return Iterables.isEmpty(resources);
68 }
69
70 public boolean isResourceModified(final HttpServletRequest request, final HttpServletResponse response)
71 {
72 return any(resources, new Predicate<DownloadableResource>()
73 {
74 public boolean apply(final DownloadableResource resource)
75 {
76 return resource.isResourceModified(request, response);
77 }
78 });
79 }
80
81 public void serveResource(final HttpServletRequest request, final HttpServletResponse response) throws DownloadException
82 {
83 if (log.isDebugEnabled())
84 {
85 log.debug("Start to serve batch " + toString());
86 }
87
88 OutputStream out;
89 try
90 {
91 out = response.getOutputStream();
92 }
93 catch (final IOException e)
94 {
95 throw new DownloadException(e);
96 }
97
98 streamResourceInternal(out, resourceContentAnnotators);
99 }
100
101 public void streamResource(final OutputStream originalOut) throws DownloadException
102 {
103 streamResourceInternal(originalOut,resourceContentAnnotators);
104 }
105
106 private void streamResourceInternal(final OutputStream originalOut, final ResourceContentAnnotator[] annotators) throws DownloadException
107 {
108 final FileCacheStreamProvider streamProvider = new FileCacheStreamProvider() {
109 @Override
110 public void writeStream(OutputStream dest) throws DownloadException {
111 for (final DownloadableResource resource : resources)
112 {
113 try
114 {
115 applyBeforeAnnotators(dest, annotators);
116 resource.streamResource(dest);
117 applyAfterAnnotators(dest, annotators);
118 }
119 catch (IOException ex)
120 {
121 throw new DownloadException(ex);
122 }
123 }
124 }
125 };
126 cacher.stream(originalOut, streamProvider);
127 }
128
129 public String getContentType()
130 {
131 final String contentType = params.get("content-type");
132 if (contentType != null)
133 {
134 return contentType;
135 }
136 return null;
137 }
138
139 public Map<String, String> getParams()
140 {
141 return params;
142 }
143
144 public String getType()
145 {
146 return type;
147 }
148
149 private void applyBeforeAnnotators(OutputStream str, ResourceContentAnnotator[] annotators) throws IOException
150 {
151 for (ResourceContentAnnotator annotator : annotators)
152 {
153 annotator.before(str);
154 }
155 }
156
157
158
159
160
161
162
163 private void applyAfterAnnotators(OutputStream str, ResourceContentAnnotator[] annotators) throws IOException
164 {
165 for (int i = annotators.length - 1; i >= 0; i--)
166 {
167 annotators[i].after(str);
168 }
169 }
170
171
172
173
174 private ResourceContentAnnotator[] getAnnotators()
175 {
176 if ("js".equals(this.getType()))
177 {
178 String trycatch = System.getProperty(DefaultResourceBatchingConfiguration.PLUGIN_WEBRESOURCE_TRY_CATCH_WRAPPING);
179 if (trycatch != null && Boolean.parseBoolean(trycatch))
180 {
181 return JS_WRAP_ANNOTATORS;
182 }
183 else
184 {
185 return DEFAULT_ANNOTATORS;
186 }
187 }
188 else
189 {
190 return DEFAULT_ANNOTATORS;
191 }
192 }
193 }