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.io.InputStream;
20 import java.text.DateFormat;
21 import java.text.ParseException;
22 import java.text.SimpleDateFormat;
23 import java.util.Date;
24
25 import javax.jcr.ItemNotFoundException;
26 import javax.jcr.Node;
27 import javax.jcr.PathNotFoundException;
28 import javax.jcr.version.VersionHistory;
29 import javax.ws.rs.DefaultValue;
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.QueryParam;
35 import javax.ws.rs.core.Response;
36
37 import org.exoplatform.common.http.HTTPStatus;
38 import org.exoplatform.services.jcr.RepositoryService;
39 import org.exoplatform.services.jcr.ext.app.SessionProviderService;
40 import org.exoplatform.services.jcr.ext.common.SessionProvider;
41 import org.exoplatform.services.log.ExoLogger;
42 import org.exoplatform.services.log.Log;
43 import org.exoplatform.services.rest.resource.ResourceContainer;
44 import org.exoplatform.services.wcm.core.NodetypeConstant;
45 import org.exoplatform.services.wcm.core.WCMService;
46 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
47
48
49
50
51
52
53
54
55 @Path("/images/")
56 public class RESTImagesRendererService implements ResourceContainer{
57
58
59 private SessionProviderService sessionProviderService;
60
61
62 private RepositoryService repositoryService;
63
64
65 private static final Log LOG = ExoLogger.getLogger(RESTImagesRendererService.class.getName());
66
67
68 private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
69
70
71 private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
72
73
74 private static String DEFAULT_MIME_TYPE = "image/jpg";
75
76
77 private static String PROPERTY_MIME_TYPE = "jcr:mimeType";
78
79
80
81
82
83
84
85 public RESTImagesRendererService(RepositoryService repositoryService, SessionProviderService sessionProviderService) {
86 this.repositoryService = repositoryService;
87 this.sessionProviderService = sessionProviderService;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101 @GET
102 @Path("/{repositoryName}/{workspaceName}/{nodeIdentifier}")
103 public Response serveImage(@PathParam("repositoryName") String repositoryName,
104 @PathParam("workspaceName") String workspaceName,
105 @PathParam("nodeIdentifier") String nodeIdentifier,
106 @QueryParam("param") @DefaultValue("file") String param,
107 @HeaderParam("If-Modified-Since") String ifModifiedSince) {
108 try {
109 SessionProvider sessionProvider = sessionProviderService.getSessionProvider(null);
110 WCMService wcmService = WCMCoreUtils.getService(WCMService.class);
111 Node node = wcmService.getReferencedContent(sessionProvider, workspaceName, nodeIdentifier);
112 if (node == null) return Response.status(HTTPStatus.NOT_FOUND).build();
113
114 if ("file".equals(param)) {
115 Node dataNode = null;
116 if(WCMCoreUtils.isNodeTypeOrFrozenType(node, NodetypeConstant.NT_FILE)) {
117 dataNode = node;
118 }else if(node.isNodeType("nt:versionedChild")) {
119 VersionHistory versionHistory = (VersionHistory)node.getProperty("jcr:childVersionHistory").getNode();
120 String versionableUUID = versionHistory.getVersionableUUID();
121 dataNode = sessionProvider.getSession(workspaceName,
122 repositoryService.getCurrentRepository())
123 .getNodeByUUID(versionableUUID);
124 }else {
125 return Response.status(HTTPStatus.NOT_FOUND).build();
126 }
127
128 if (ifModifiedSince != null && isModified(ifModifiedSince, dataNode) == false) {
129 return Response.notModified().build();
130 }
131
132 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
133
134 Node jcrContentNode = dataNode.getNode("jcr:content");
135 String mimeType = DEFAULT_MIME_TYPE;
136 if (jcrContentNode.hasProperty(PROPERTY_MIME_TYPE)) {
137 mimeType = jcrContentNode.getProperty(PROPERTY_MIME_TYPE).getString();
138 }
139 InputStream jcrData = jcrContentNode.getProperty("jcr:data").getStream();
140 return Response.ok(jcrData, mimeType).header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
141 }
142
143 if (ifModifiedSince != null && isModified(ifModifiedSince, node) == false) {
144 return Response.notModified().build();
145 }
146
147 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
148 InputStream jcrData = node.getProperty(param).getStream();
149 return Response.ok(jcrData, DEFAULT_MIME_TYPE).header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
150
151 } catch (PathNotFoundException e) {
152 return Response.status(HTTPStatus.NOT_FOUND).build();
153 }catch (ItemNotFoundException e) {
154 return Response.status(HTTPStatus.NOT_FOUND).build();
155 }catch (Exception e) {
156 if (LOG.isErrorEnabled()) {
157 LOG.error("Error when serveImage: ", e);
158 }
159 return Response.serverError().build();
160 }
161 }
162
163
164
165
166
167
168
169 private Date getLastModifiedDate(Node node) throws Exception {
170 Date lastModifiedDate = null;
171 if (node.hasNode("jcr:content") && node.getNode("jcr:content").hasProperty("jcr:lastModified")) {
172 lastModifiedDate = node.getNode("jcr:content").getProperty("jcr:lastModified").getDate().getTime();
173 } else if (node.hasProperty("exo:dateModified")) {
174 lastModifiedDate = node.getProperty("exo:dateModified").getDate().getTime();
175 } else if (node.hasProperty("jcr:created")){
176 lastModifiedDate = node.getProperty("jcr:created").getDate().getTime();
177 }
178 return lastModifiedDate;
179 }
180
181
182
183
184
185
186
187
188 private boolean isModified(String ifModifiedSince, Node node) throws Exception {
189
190 DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
191 if(ifModifiedSince == null || ifModifiedSince.length() == 0)
192 return false;
193 try {
194 Date ifModifiedSinceDate = dateFormat.parse(ifModifiedSince);
195
196 Date lastModifiedDate = getLastModifiedDate(node);
197
198 if (lastModifiedDate != null && ifModifiedSinceDate != null &&
199 ifModifiedSinceDate.getTime() >= lastModifiedDate.getTime()) {
200 return false;
201 }
202 return true;
203 } catch(ParseException pe) {
204 return false;
205 }
206
207 }
208
209 }