1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.wcm.connector.collaboration;
18
19 import java.awt.image.BufferedImage;
20 import java.io.BufferedInputStream;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.InputStream;
24 import java.text.DateFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Date;
28
29 import javax.jcr.*;
30 import javax.ws.rs.GET;
31 import javax.ws.rs.HeaderParam;
32 import javax.ws.rs.Path;
33 import javax.ws.rs.PathParam;
34 import javax.ws.rs.core.Response;
35
36 import org.exoplatform.container.component.ComponentPlugin;
37 import org.exoplatform.ecm.utils.text.Text;
38 import org.exoplatform.services.cms.link.LinkManager;
39 import org.exoplatform.services.cms.link.NodeFinder;
40 import org.exoplatform.services.cms.thumbnail.ThumbnailPlugin;
41 import org.exoplatform.services.cms.thumbnail.ThumbnailService;
42 import org.exoplatform.services.cms.thumbnail.impl.ThumbnailUtils;
43 import org.exoplatform.services.jcr.RepositoryService;
44 import org.exoplatform.services.jcr.core.ManageableRepository;
45 import org.exoplatform.services.jcr.impl.core.NodeImpl;
46 import org.exoplatform.services.log.ExoLogger;
47 import org.exoplatform.services.log.Log;
48 import org.exoplatform.services.rest.resource.ResourceContainer;
49 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
50
51
52
53
54
55
56
57
58
59
60
61
62
63 @Path("/thumbnailImage/")
64 public class ThumbnailRESTService implements ResourceContainer {
65
66
67 private static final Log LOG = ExoLogger.getLogger(ThumbnailRESTService.class.getName());
68
69
70 private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
71
72
73 private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
74
75 private final RepositoryService repositoryService_;
76 private final ThumbnailService thumbnailService_;
77 private final NodeFinder nodeFinder_;
78 private final LinkManager linkManager_;
79
80 public ThumbnailRESTService(RepositoryService repositoryService,
81 ThumbnailService thumbnailService,
82 NodeFinder nodeFinder,
83 LinkManager linkManager) {
84 repositoryService_ = repositoryService;
85 thumbnailService_ = thumbnailService;
86 nodeFinder_ = nodeFinder;
87 linkManager_ = linkManager;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102 @Path("/medium/{repoName}/{workspaceName}/{nodePath:.*}/")
103 @GET
104 public Response getThumbnailImage(@PathParam("repoName") String repoName,
105 @PathParam("workspaceName") String workspaceName,
106 @PathParam("nodePath") String nodePath,
107 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
108 return getThumbnailByType(workspaceName,
109 nodePath,
110 ThumbnailService.MEDIUM_SIZE,
111 ifModifiedSince);
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125 @Path("/big/{repoName}/{workspaceName}/{nodePath:.*}/")
126 @GET
127 public Response getCoverImage(@PathParam("repoName") String repoName,
128 @PathParam("workspaceName") String workspaceName,
129 @PathParam("nodePath") String nodePath,
130 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
131 return getThumbnailByType(workspaceName, nodePath, ThumbnailService.BIG_SIZE, ifModifiedSince);
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145 @Path("/large/{repoName}/{workspaceName}/{nodePath:.*}/")
146 @GET
147 public Response getLargeImage(@PathParam("repoName") String repoName,
148 @PathParam("workspaceName") String workspaceName,
149 @PathParam("nodePath") String nodePath,
150 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
151 return getThumbnailByType(workspaceName, nodePath, ThumbnailService.BIG_SIZE, ifModifiedSince);
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165 @Path("/small/{repoName}/{workspaceName}/{nodePath:.*}/")
166 @GET
167 public Response getSmallImage(@PathParam("repoName") String repoName,
168 @PathParam("workspaceName") String workspaceName,
169 @PathParam("nodePath") String nodePath,
170 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
171 return getThumbnailByType(workspaceName, nodePath, ThumbnailService.SMALL_SIZE, ifModifiedSince);
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186 @Path("/custom/{size}/{repoName}/{workspaceName}/{nodePath:.*}/")
187 @GET
188 public Response getCustomImage(@PathParam("size") String size,
189 @PathParam("repoName") String repoName,
190 @PathParam("workspaceName") String workspaceName,
191 @PathParam("nodePath") String nodePath,
192 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
193 return getThumbnailByType(workspaceName, nodePath, "exo:"+size, ifModifiedSince);
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207 @Path("/origin/{repoName}/{workspaceName}/{nodePath:.*}/")
208 @GET
209 public Response getOriginImage(@PathParam("repoName") String repoName,
210 @PathParam("workspaceName") String workspaceName,
211 @PathParam("nodePath") String nodePath,
212 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
213 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
214 if (!thumbnailService_.isEnableThumbnail())
215 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
216 Node showingNode = getShowingNode(workspaceName, nodePath);
217 Node targetNode = getTargetNode(showingNode);
218 if (targetNode.isNodeType("nt:file") || targetNode.isNodeType("nt:resource")) {
219 Node content = targetNode;
220 if (targetNode.isNodeType("nt:file"))
221 content = targetNode.getNode("jcr:content");
222 if (ifModifiedSince != null) {
223
224 Date ifModifiedSinceDate = dateFormat.parse(ifModifiedSince);
225
226
227 Date lastModifiedDate = content.getProperty("jcr:lastModified").getDate().getTime();
228
229
230 if (ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
231 return Response.notModified().build();
232 }
233 }
234
235 String mimeType = content.getProperty("jcr:mimeType").getString();
236 for (ComponentPlugin plugin : thumbnailService_.getComponentPlugins()) {
237 if (plugin instanceof ThumbnailPlugin) {
238 ThumbnailPlugin thumbnailPlugin = (ThumbnailPlugin) plugin;
239 if (thumbnailPlugin.getMimeTypes().contains(mimeType)) {
240 InputStream inputStream = content.getProperty("jcr:data").getStream();
241 return Response.ok(inputStream, "image").header(LAST_MODIFIED_PROPERTY,
242 dateFormat.format(new Date())).build();
243 }
244 }
245 }
246 }
247
248 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
249 }
250
251
252
253
254
255
256
257
258
259
260 @Path("/originImage/{nodePath:.*}/")
261 @GET
262 public Response getLocalImage(@PathParam("nodePath") String nodePath,
263 @HeaderParam("If-Modified-Since") String ifModifiedSince) throws Exception {
264 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
265 if (!thumbnailService_.isEnableThumbnail())
266 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
267
268
269 try {
270 File file = new File(nodePath);
271 FileInputStream inputStream = new FileInputStream(file);
272 BufferedInputStream buf = new BufferedInputStream(inputStream);
273
274 return Response.ok(buf, "image").header(LAST_MODIFIED_PROPERTY,
275 dateFormat.format(new Date())).build();
276 } catch (Exception e) {
277 if (LOG.isErrorEnabled()) {
278 LOG.error(e);
279 }
280 }
281 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
282 }
283
284 private Response getThumbnailByType(String workspaceName, String nodePath,
285 String propertyName, String ifModifiedSince) throws Exception {
286 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
287 if (!thumbnailService_.isEnableThumbnail())
288 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
289 Node showingNode = getShowingNode(workspaceName, nodePath);
290 String identifier = ((NodeImpl) showingNode).getInternalIdentifier();
291 Node targetNode = getTargetNode(showingNode);
292 Node parentNode = null;
293 try {
294 parentNode = showingNode.getParent();
295 } catch (AccessDeniedException e) {
296 Session session = WCMCoreUtils.getSystemSessionProvider().getSession(workspaceName,
297 repositoryService_.getCurrentRepository());
298 parentNode = session.getItem(showingNode.getPath()).getParent();
299 }
300 if(targetNode.isNodeType("nt:file")) {
301 Node content = targetNode.getNode("jcr:content");
302 String mimeType = content.getProperty("jcr:mimeType").getString();
303 for(ComponentPlugin plugin : thumbnailService_.getComponentPlugins()) {
304 if(plugin instanceof ThumbnailPlugin) {
305 ThumbnailPlugin thumbnailPlugin = (ThumbnailPlugin) plugin;
306 if(thumbnailPlugin.getMimeTypes().contains(mimeType)) {
307 Node thumbnailFolder = ThumbnailUtils.getThumbnailFolder(parentNode);
308
309 Node thumbnailNode = ThumbnailUtils.getThumbnailNode(thumbnailFolder, identifier);
310
311 if(!thumbnailNode.hasProperty(propertyName)) {
312 try {
313 BufferedImage image = thumbnailPlugin.getBufferedImage(content, targetNode.getPath());
314 thumbnailService_.addThumbnailImage(thumbnailNode, image, propertyName);
315 } catch (Exception e) {
316 throw new Exception("Failed to get image.", e);
317 }
318 }
319
320 if(ifModifiedSince != null && thumbnailNode.hasProperty(ThumbnailService.THUMBNAIL_LAST_MODIFIED)) {
321
322 Date ifModifiedSinceDate = dateFormat.parse(ifModifiedSince);
323
324
325 Date lastModifiedDate = thumbnailNode.getProperty(ThumbnailService.THUMBNAIL_LAST_MODIFIED)
326 .getDate()
327 .getTime();
328
329
330 if (ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
331 return Response.notModified().build();
332 }
333 }
334 InputStream inputStream = null;
335 if(thumbnailNode.hasProperty(propertyName)) {
336 inputStream = thumbnailNode.getProperty(propertyName).getStream();
337 }
338 return Response.ok(inputStream, "image").header(LAST_MODIFIED_PROPERTY,
339 dateFormat.format(new Date())).build();
340 }
341 }
342 }
343 }
344 return getThumbnailRes(parentNode, identifier, propertyName, ifModifiedSince);
345 }
346
347 private Response getThumbnailRes(Node parentNode,
348 String identifier,
349 String propertyName,
350 String ifModifiedSince) throws Exception {
351
352 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
353 if(parentNode.hasNode(ThumbnailService.EXO_THUMBNAILS_FOLDER)) {
354 Node thumbnailFolder = parentNode.getNode(ThumbnailService.EXO_THUMBNAILS_FOLDER);
355 if(thumbnailFolder.hasNode(identifier)) {
356 Node thumbnailNode = thumbnailFolder.getNode(identifier);
357 if (ifModifiedSince != null && thumbnailNode.hasProperty("exo:dateModified")) {
358
359 Date ifModifiedSinceDate = dateFormat.parse(ifModifiedSince);
360
361
362 Date lastModifiedDate = thumbnailNode.getProperty("exo:dateModified").getDate().getTime();
363
364
365 if (ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
366 return Response.notModified().build();
367 }
368 }
369
370 if(thumbnailNode.hasProperty(propertyName)) {
371 InputStream inputStream = thumbnailNode.getProperty(propertyName).getStream();
372 return Response.ok(inputStream, "image").header(LAST_MODIFIED_PROPERTY,
373 dateFormat.format(new Date())).build();
374 }
375 }
376 }
377 return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
378 }
379
380 private String getNodePath(String nodePath) throws Exception {
381 ArrayList<String> encodeNameArr = new ArrayList<String>();
382 if(!nodePath.equals("/")) {
383 for(String name : nodePath.split("/")) {
384 if(name.length() > 0) {
385 encodeNameArr.add(Text.escapeIllegalJcrChars(name));
386 }
387 }
388 StringBuilder encodedPath = new StringBuilder();
389 for(String encodedName : encodeNameArr) {
390 encodedPath.append("/").append(encodedName);
391 }
392 nodePath = encodedPath.toString();
393 }
394 return nodePath;
395 }
396
397 private Node getTargetNode(Node showingNode) throws Exception {
398 Node targetNode = null;
399 if (linkManager_.isLink(showingNode)) {
400 try {
401 targetNode = linkManager_.getTarget(showingNode);
402 } catch (ItemNotFoundException e) {
403 targetNode = showingNode;
404 }
405 } else {
406 targetNode = showingNode;
407 }
408 return targetNode;
409 }
410
411 private Node getShowingNode(String workspaceName, String nodePath) throws Exception {
412 ManageableRepository repository = repositoryService_.getCurrentRepository();
413 Session session = WCMCoreUtils.getUserSessionProvider().getSession(workspaceName, repository);
414 Node showingNode = null;
415 if(nodePath.equals("/")) {
416 showingNode = session.getRootNode();
417 } else {
418 if (!nodePath.startsWith("/")) {
419 nodePath = "/" + nodePath;
420 }
421 try {
422 showingNode = (Node) nodeFinder_.getItem(session, nodePath);
423 } catch (PathNotFoundException e) {
424 showingNode = (Node) nodeFinder_.getItem(session, getNodePath(nodePath));
425 }
426 }
427 return showingNode;
428 }
429
430 }