1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.webdav;
18
19 import java.io.InputStream;
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.util.GregorianCalendar;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Queue;
26
27 import javax.jcr.Item;
28 import javax.jcr.NoSuchWorkspaceException;
29 import javax.jcr.Node;
30 import javax.jcr.NodeIterator;
31 import javax.jcr.PathNotFoundException;
32 import javax.jcr.RepositoryException;
33 import javax.jcr.Session;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.HEAD;
37 import javax.ws.rs.HeaderParam;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.QueryParam;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.MultivaluedMap;
45 import javax.ws.rs.core.Response;
46 import javax.ws.rs.core.UriInfo;
47
48 import org.apache.commons.lang.StringUtils;
49 import org.exoplatform.common.http.HTTPStatus;
50 import org.exoplatform.common.util.HierarchicalProperty;
51 import org.exoplatform.commons.utils.MimeTypeResolver;
52 import org.exoplatform.container.xml.InitParams;
53 import org.exoplatform.ecm.utils.text.Text;
54 import org.exoplatform.services.cms.CmsService;
55 import org.exoplatform.services.cms.documents.AutoVersionService;
56 import org.exoplatform.services.cms.drives.DriveData;
57 import org.exoplatform.services.cms.drives.ManageDriveService;
58 import org.exoplatform.services.cms.impl.Utils;
59 import org.exoplatform.services.cms.jcrext.activity.ActivityCommonService;
60 import org.exoplatform.services.cms.link.LinkUtils;
61 import org.exoplatform.services.cms.link.NodeFinder;
62 import org.exoplatform.services.jcr.RepositoryService;
63 import org.exoplatform.services.jcr.ext.app.ThreadLocalSessionProviderService;
64 import org.exoplatform.services.jcr.webdav.util.InitParamsDefaults;
65 import org.exoplatform.services.jcr.webdav.util.TextUtil;
66 import org.exoplatform.services.listener.ListenerService;
67 import org.exoplatform.services.log.ExoLogger;
68 import org.exoplatform.services.log.Log;
69 import org.exoplatform.services.rest.ExtHttpHeaders;
70 import org.exoplatform.services.rest.ext.webdav.method.ACL;
71 import org.exoplatform.services.rest.ext.webdav.method.CHECKIN;
72 import org.exoplatform.services.rest.ext.webdav.method.CHECKOUT;
73 import org.exoplatform.services.rest.ext.webdav.method.COPY;
74 import org.exoplatform.services.rest.ext.webdav.method.LOCK;
75 import org.exoplatform.services.rest.ext.webdav.method.MKCOL;
76 import org.exoplatform.services.rest.ext.webdav.method.MOVE;
77 import org.exoplatform.services.rest.ext.webdav.method.OPTIONS;
78 import org.exoplatform.services.rest.ext.webdav.method.ORDERPATCH;
79 import org.exoplatform.services.rest.ext.webdav.method.PROPFIND;
80 import org.exoplatform.services.rest.ext.webdav.method.PROPPATCH;
81 import org.exoplatform.services.rest.ext.webdav.method.REPORT;
82 import org.exoplatform.services.rest.ext.webdav.method.SEARCH;
83 import org.exoplatform.services.rest.ext.webdav.method.UNCHECKOUT;
84 import org.exoplatform.services.rest.ext.webdav.method.UNLOCK;
85 import org.exoplatform.services.rest.ext.webdav.method.VERSIONCONTROL;
86 import org.exoplatform.services.rest.impl.MultivaluedMapImpl;
87 import org.exoplatform.services.wcm.core.NodetypeConstant;
88 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
89
90
91
92
93
94
95
96
97
98 @Path("/jcr/")
99 public class WebDavServiceImpl extends org.exoplatform.services.jcr.webdav.WebDavServiceImpl {
100
101
102
103
104 private static final Log LOG = ExoLogger.getLogger(WebDavServiceImpl.class.getName());
105
106 private final String POST_UPLOAD_CONTENT_EVENT = "WebDavService.event.postUpload";
107
108 private final String PERSONAL_DRIVE_PREFIX = "/Users/${userId}/Private";
109
110 private final String GROUP_DRIVE_PREFIX = "/Groups${groupId}/Documents";
111
112 private final String PERSONAL_GROUP_DRIVE_WORKSPACE = "collaboration";
113
114
115 private final NodeFinder nodeFinder;
116
117 private final RepositoryService repositoryService;
118
119 private ListenerService listenerService;
120
121 private final MimeTypeResolver mimeTypeResolver;
122
123 public WebDavServiceImpl(InitParams params,
124 RepositoryService repositoryService,
125 ThreadLocalSessionProviderService sessionProviderService,
126 NodeFinder nodeFinder, AutoVersionService autoVersionService, ManageDriveService manageDriveService) throws Exception
127 {
128 super(params, repositoryService, sessionProviderService);
129 this.repositoryService = repositoryService;
130 this.nodeFinder = nodeFinder;
131 this.listenerService = WCMCoreUtils.getService(ListenerService.class);
132 this.mimeTypeResolver = new MimeTypeResolver();
133 this.mimeTypeResolver.setDefaultMimeType(InitParamsDefaults.FILE_MIME_TYPE);
134
135 List<String> lstDriveAutoVersion = autoVersionService.getDriveAutoVersion();
136 MultivaluedMap<String, String> allowedAutoVersionPath = new MultivaluedMapImpl();
137 if (!lstDriveAutoVersion.isEmpty())
138 {
139 for (String driverName : lstDriveAutoVersion)
140 {
141 DriveData driveData = manageDriveService.getDriveByName(StringUtils.trim(driverName));
142 if (driveData != null)
143 {
144 String driveHome = driveData.getHomePath();
145 String workspace = driveData.getWorkspace();
146
147 if (driveHome.startsWith(PERSONAL_DRIVE_PREFIX) && PERSONAL_GROUP_DRIVE_WORKSPACE.equals(workspace))
148 {
149 allowedAutoVersionPath.add(driveData.getWorkspace(), "/Users");
150 }
151 else if (driveHome.startsWith(GROUP_DRIVE_PREFIX) && PERSONAL_GROUP_DRIVE_WORKSPACE.equals(workspace))
152 {
153 allowedAutoVersionPath.add(driveData.getWorkspace(), "/Groups");
154 }
155 else
156 {
157 allowedAutoVersionPath.add(driveData.getWorkspace(), driveHome);
158 }
159 }
160 }
161 }
162 webDavServiceInitParams.setAllowedAutoVersionPath(allowedAutoVersionPath);
163 webDavServiceInitParams.setEnableAutoVersion(true);
164 }
165
166 private String getRealDestinationHeader(String baseURI, String repoName, String destinationHeader) {
167 String serverURI = baseURI + "/jcr/" + repoName;
168
169 destinationHeader = TextUtil.unescape(destinationHeader, '%');
170
171 if (!destinationHeader.startsWith(serverURI)) {
172 return null;
173 }
174
175 String destPath = destinationHeader.substring(serverURI.length() + 1);
176
177 try {
178 Item item = nodeFinder.getItem(workspaceName(destPath),
179 LinkUtils.getParentPath(path(destPath)),
180 true);
181 return item.getSession().getWorkspace().getName()
182 + LinkUtils.createPath(item.getPath(), LinkUtils.getItemName(path(destPath)));
183 } catch (RepositoryException e) {
184 if (LOG.isWarnEnabled()) {
185 LOG.warn("Cannot find the item at " + repoName + "/" + destPath, e);
186 }
187 return null;
188 }
189 }
190
191 @CHECKIN
192 @Path("/{repoName}/{repoPath:.*}/")
193 public Response checkin(@PathParam("repoName") String repoName,
194 @PathParam("repoPath") String repoPath,
195 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
196 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
197
198 try {
199 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
200 repoPath = convertRepoPath(repoPath, true);
201 } catch (PathNotFoundException exc) {
202 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
203 } catch (NoSuchWorkspaceException exc) {
204 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
205 } catch (Exception e) {
206 if (LOG.isWarnEnabled()) {
207 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
208 }
209 return Response.serverError().build();
210 }
211 return super.checkin(repoName, repoPath, lockTokenHeader, ifHeader);
212 }
213
214 @CHECKOUT
215 @Path("/{repoName}/{repoPath:.*}/")
216 public Response checkout(@PathParam("repoName") String repoName,
217 @PathParam("repoPath") String repoPath,
218 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
219 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
220 try {
221 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
222 repoPath = convertRepoPath(repoPath, true);
223 } catch (PathNotFoundException exc) {
224 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
225 } catch (NoSuchWorkspaceException exc) {
226 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
227 } catch (Exception e) {
228 if (LOG.isWarnEnabled()) {
229 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
230 }
231 return Response.serverError().build();
232 }
233 return super.checkout(repoName, repoPath, lockTokenHeader, ifHeader);
234 }
235
236 @COPY
237 @Path("/{repoName}/{repoPath:.*}/")
238 public Response copy(@PathParam("repoName") String repoName,
239 @PathParam("repoPath") String repoPath,
240 @HeaderParam(ExtHttpHeaders.DESTINATION) String destinationHeader,
241 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
242 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
243 @HeaderParam(ExtHttpHeaders.DEPTH) String depthHeader,
244 @HeaderParam(ExtHttpHeaders.OVERWRITE) String overwriteHeader,
245 @Context UriInfo uriInfo,
246 HierarchicalProperty body) {
247
248 try {
249 repoPath = convertRepoPath(repoPath, false);
250 } catch (PathNotFoundException exc) {
251 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
252 } catch (NoSuchWorkspaceException exc) {
253 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
254 } catch (Exception e) {
255 if (LOG.isWarnEnabled()) {
256 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
257 }
258 return Response.serverError().build();
259 }
260 String realDestinationHeader = getRealDestinationHeader(uriInfo.getPath(), repoName, destinationHeader);
261 if (realDestinationHeader != null) {
262 destinationHeader = realDestinationHeader;
263 }
264 return super.copy(repoName,
265 repoPath,
266 destinationHeader,
267 lockTokenHeader,
268 ifHeader,
269 depthHeader,
270 overwriteHeader,
271 uriInfo,
272 body);
273 }
274
275 @GET
276 @Path("/{repoName}/{repoPath:.*}/")
277 public Response get(@PathParam("repoName") String repoName,
278 @PathParam("repoPath") String repoPath,
279 @HeaderParam(ExtHttpHeaders.RANGE) String rangeHeader,
280 @HeaderParam(ExtHttpHeaders.IF_MODIFIED_SINCE) String ifModifiedSince,
281 @HeaderParam(ExtHttpHeaders.IF_NONE_MATCH) String ifNoneMatch,
282 @QueryParam("version") String version,
283 @Context UriInfo uriInfo) {
284
285 try {
286 repoPath = convertRepoPath(repoPath, true);
287 } catch (PathNotFoundException exc) {
288 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
289 } catch (NoSuchWorkspaceException exc) {
290 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
291 } catch (Exception e) {
292 if (LOG.isWarnEnabled()) {
293 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
294 }
295 return Response.serverError().build();
296 }
297 Response response = super.get(repoName, repoPath, rangeHeader, ifModifiedSince, ifNoneMatch, version, uriInfo);
298 if(HTTPStatus.OK == response.getStatus()) {
299 return Response.fromResponse(response)
300 .header("Access-Control-Allow-Origin", uriInfo.getRequestUri().getHost())
301 .header("Access-Control-Allow-Credentials", true)
302 .header("Access-Control-Allow-Methods", "ACL, CANCELUPLOAD, CHECKIN, CHECKOUT, COPY, DELETE, GET, HEAD, LOCK, MKCALENDAR, MKCOL, " +
303 "MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, REPORT, SEARCH, UNCHECKOUT, UNLOCK, UPDATE, VERSION-CONTROL")
304 .header("Access-Control-Allow-Headers", "Overwrite, Destination, Content-Type, Depth, User-Agent, Translate, Range, Content-Range," +
305 " Timeout, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Location, Lock-Token, If")
306 .header("Access-Control-Expose-Header", "DAV, content-length, Allow")
307 .header("Access-Control-Max-Age", 3600)
308 .build();
309 }
310 return response;
311 }
312
313 @HEAD
314 @Path("/{repoName}/{repoPath:.*}/")
315 public Response head(@PathParam("repoName") String repoName,
316 @PathParam("repoPath") String repoPath,
317 @Context UriInfo uriInfo) {
318
319 try {
320 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
321 repoPath = convertRepoPath(repoPath, true);
322 } catch (PathNotFoundException exc) {
323 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
324 } catch (NoSuchWorkspaceException exc) {
325 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
326 } catch (Exception e) {
327 if (LOG.isWarnEnabled()) {
328 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
329 }
330 return Response.serverError().build();
331 }
332 return super.head(repoName, repoPath, uriInfo);
333 }
334
335 @LOCK
336 @Path("/{repoName}/{repoPath:.*}/")
337 public Response lock(@PathParam("repoName") String repoName,
338 @PathParam("repoPath") String repoPath,
339 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
340 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
341 @HeaderParam(ExtHttpHeaders.DEPTH) String depthHeader,
342 HierarchicalProperty body) {
343
344 try {
345 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
346 repoPath = convertRepoPath(repoPath, true);
347 } catch (PathNotFoundException exc) {
348 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
349 } catch (NoSuchWorkspaceException exc) {
350 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
351 } catch (Exception e) {
352 if (LOG.isWarnEnabled()) {
353 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
354 }
355 return Response.serverError().build();
356 }
357 return super.lock(repoName, repoPath, lockTokenHeader, ifHeader, depthHeader, body);
358 }
359
360 @UNLOCK
361 @Path("/{repoName}/{repoPath:.*}/")
362 public Response unlock(@PathParam("repoName") String repoName,
363 @PathParam("repoPath") String repoPath,
364 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
365 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
366
367 try {
368 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
369 repoPath = convertRepoPath(repoPath, true);
370 } catch (PathNotFoundException exc) {
371 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
372 } catch (NoSuchWorkspaceException exc) {
373 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
374 } catch (Exception e) {
375 if (LOG.isWarnEnabled()) {
376 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
377 }
378 return Response.serverError().build();
379 }
380 return super.unlock(repoName, repoPath, lockTokenHeader, ifHeader);
381 }
382
383 @OPTIONS
384 @Path("/{repoName}/{path:.*}/")
385 public Response options(@PathParam("path") String path) {
386 return super.options(path);
387 }
388
389 @ORDERPATCH
390 @Path("/{repoName}/{repoPath:.*}/")
391 public Response order(@PathParam("repoName") String repoName,
392 @PathParam("repoPath") String repoPath,
393 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
394 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
395 @Context UriInfo uriInfo,
396 HierarchicalProperty body) {
397
398 try {
399 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
400 repoPath = convertRepoPath(repoPath, true);
401 } catch (PathNotFoundException exc) {
402 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
403 } catch (NoSuchWorkspaceException exc) {
404 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
405 } catch (Exception e) {
406 if (LOG.isWarnEnabled()) {
407 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
408 }
409 return Response.serverError().build();
410 }
411 return super.order(repoName, repoPath, lockTokenHeader, ifHeader, uriInfo, body);
412 }
413
414 @PROPFIND
415 @Path("/{repoName}/{repoPath:.*}/")
416 public Response propfind(@PathParam("repoName") String repoName,
417 @PathParam("repoPath") String repoPath,
418 @HeaderParam(ExtHttpHeaders.DEPTH) String depthHeader,
419 @Context UriInfo uriInfo,
420 HierarchicalProperty body) {
421
422 try {
423 repoPath = convertRepoPath(repoPath, true);
424 } catch (PathNotFoundException exc) {
425 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
426 } catch (NoSuchWorkspaceException exc) {
427 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
428 } catch (Exception e) {
429 if (LOG.isWarnEnabled()) {
430 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
431 }
432 return Response.serverError().build();
433 }
434 return super.propfind(repoName, repoPath, depthHeader, uriInfo, body);
435 }
436
437 @PROPPATCH
438 @Path("/{repoName}/{repoPath:.*}/")
439 public Response proppatch(@PathParam("repoName") String repoName,
440 @PathParam("repoPath") String repoPath,
441 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
442 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
443 @Context UriInfo uriInfo,
444 HierarchicalProperty body) {
445
446 try {
447 repoPath = convertRepoPath(repoPath, true);
448 } catch (PathNotFoundException exc) {
449 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
450 } catch (NoSuchWorkspaceException exc) {
451 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
452 } catch (Exception e) {
453 if (LOG.isWarnEnabled()) {
454 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
455 }
456 return Response.serverError().build();
457 }
458 return super.proppatch(repoName, repoPath, lockTokenHeader, ifHeader, uriInfo, body);
459 }
460
461 @PUT
462 @Path("/{repoName}/{repoPath:.*}/")
463 public Response put(@PathParam("repoName") String repoName,
464 @PathParam("repoPath") String repoPath,
465 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
466 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
467 @HeaderParam(ExtHttpHeaders.FILE_NODETYPE) String fileNodeTypeHeader,
468 @HeaderParam(ExtHttpHeaders.CONTENT_NODETYPE) String nodeTypeHeader,
469 @HeaderParam(ExtHttpHeaders.CONTENT_MIXINTYPES) String mixinTypes,
470 @HeaderParam(ExtHttpHeaders.CONTENTTYPE) MediaType mediaType,
471 @HeaderParam(ExtHttpHeaders.USER_AGENT) String userAgent,
472 InputStream inputStream,
473 @Context UriInfo uriInfo) {
474 Session session = null;
475 Item item = null;
476 boolean isCreating = false;
477 ActivityCommonService activityService = null;
478 try {
479 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
480 try {
481 item = nodeFinder.getItem(workspaceName(repoPath),
482 LinkUtils.getParentPath(path(normalizePath(repoPath))),
483 true);
484 repoPath = item.getSession().getWorkspace().getName()
485 + LinkUtils.createPath(item.getPath(), Text.escapeIllegalJcrChars(LinkUtils.getItemName(path(repoPath))));
486 session = item.getSession();
487 } catch (PathNotFoundException e) {
488 item = nodeFinder.getItem(workspaceName(repoPath),
489 LinkUtils.getParentPath(path(Text.escapeIllegalJcrChars(repoPath))),
490 true);
491 repoPath = item.getSession().getWorkspace().getName()
492 + LinkUtils.createPath(item.getPath(), Text.escapeIllegalJcrChars(LinkUtils.getItemName(path(repoPath))));
493 session = item.getSession();
494 }
495 activityService = WCMCoreUtils.getService(ActivityCommonService.class);
496 if (!session.itemExists(path(repoPath))) {
497 isCreating = true;
498 }
499 } catch (PathNotFoundException exc) {
500 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
501 } catch (NoSuchWorkspaceException exc) {
502 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
503 } catch (Exception e) {
504 if (LOG.isWarnEnabled()) {
505 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
506 }
507 return Response.serverError().build();
508 }
509
510 Response res = super.put(repoName,
511 repoPath,
512 lockTokenHeader,
513 ifHeader,
514 null,
515 nodeTypeHeader,
516 mixinTypes,
517 mediaType,
518 userAgent,
519 inputStream,
520 uriInfo);
521 try {
522
523 boolean pushAs = markTempFilesToHidden(repoPath);
524 Node currentNode = (Node) session.getItem(path(repoPath));
525 if (isCreating) {
526 if (userAgent!= null && userAgent.contains("Microsoft")) {
527 activityService.setCreating(currentNode, true);
528 }
529 }else {
530 activityService.setCreating(currentNode, false);
531 }
532
533 try {
534 if(isCreating && pushAs)
535 listenerService.broadcast(ActivityCommonService.FILE_CREATED_ACTIVITY, null, currentNode);
536
537 if (currentNode.isCheckedOut() && !activityService.isCreating(currentNode) && pushAs)
538 listenerService.broadcast(this.POST_UPLOAD_CONTENT_EVENT, this, currentNode);
539
540 } catch (Exception e) {
541 if (LOG.isWarnEnabled()) {
542 LOG.warn("Cannot broadcast file create activity for the item at " + currentNode.getPath(), e);
543 }
544 }
545
546 } catch (PathNotFoundException npfe) {
547 return Response.status(HTTPStatus.NOT_FOUND).entity(npfe.getMessage()).build();
548 } catch (RepositoryException re) {
549 return Response.status(HTTPStatus.NOT_FOUND).entity(re.getMessage()).build();
550 } catch (Exception e) {
551 return Response.serverError().build();
552 }
553
554 return res;
555 }
556
557 @REPORT
558 @Path("/{repoName}/{repoPath:.*}/")
559 public Response report(@PathParam("repoName") String repoName,
560 @PathParam("repoPath") String repoPath,
561 @HeaderParam(ExtHttpHeaders.DEPTH) String depthHeader,
562 @Context UriInfo uriInfo,
563 HierarchicalProperty body) {
564
565 try {
566 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
567 repoPath = convertRepoPath(repoPath, true);
568 } catch (PathNotFoundException exc) {
569 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
570 } catch (NoSuchWorkspaceException exc) {
571 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
572 } catch (Exception e) {
573 if (LOG.isWarnEnabled()) {
574 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
575 }
576 return Response.serverError().build();
577 }
578 return super.report(repoName, repoPath, depthHeader, uriInfo, body);
579 }
580
581 @SEARCH
582 @Path("/{repoName}/{repoPath:.*}/")
583 public Response search(@PathParam("repoName") String repoName,
584 @PathParam("repoPath") String repoPath,
585 @Context UriInfo uriInfo,
586 HierarchicalProperty body) {
587
588 try {
589 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
590 repoPath = convertRepoPath(repoPath, true);
591 } catch (PathNotFoundException exc) {
592 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
593 } catch (NoSuchWorkspaceException exc) {
594 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
595 } catch (Exception e) {
596 if (LOG.isWarnEnabled()) {
597 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
598 }
599 return Response.serverError().build();
600 }
601 return super.search(repoName, repoPath, uriInfo, body);
602 }
603
604 @UNCHECKOUT
605 @Path("/{repoName}/{repoPath:.*}/")
606 public Response uncheckout(@PathParam("repoName") String repoName,
607 @PathParam("repoPath") String repoPath,
608 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
609 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
610
611 try {
612 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
613 repoPath = convertRepoPath(repoPath, true);
614 } catch (PathNotFoundException exc) {
615 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
616 } catch (NoSuchWorkspaceException exc) {
617 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
618 } catch (Exception e) {
619 if (LOG.isWarnEnabled()) {
620 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
621 }
622 return Response.serverError().build();
623 }
624 return super.uncheckout(repoName, repoPath, lockTokenHeader, ifHeader);
625 }
626
627 @VERSIONCONTROL
628 @Path("/{repoName}/{repoPath:.*}/")
629 public Response versionControl(@PathParam("repoName") String repoName,
630 @PathParam("repoPath") String repoPath,
631 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
632 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
633
634 try {
635 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
636 repoPath = convertRepoPath(repoPath, true);
637 } catch (PathNotFoundException exc) {
638 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
639 } catch (NoSuchWorkspaceException exc) {
640 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
641 } catch (Exception e) {
642 if (LOG.isWarnEnabled()) {
643 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
644 }
645 return Response.serverError().build();
646 }
647 return super.versionControl(repoName, repoPath, lockTokenHeader, ifHeader);
648 }
649
650 @ACL
651 @Path("/{repoName}/{repoPath:.*}/")
652 public Response acl(@PathParam("repoName") String repoName,
653 @PathParam("repoPath") String repoPath,
654 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
655 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
656 HierarchicalProperty body) {
657 try {
658 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
659 repoPath = convertRepoPath(repoPath, true);
660 } catch (PathNotFoundException exc) {
661 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
662 } catch (NoSuchWorkspaceException exc) {
663 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
664 } catch (Exception e) {
665 if (LOG.isWarnEnabled()) {
666 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
667 }
668 return Response.serverError().build();
669 }
670 return super.acl(repoName, repoPath, lockTokenHeader, ifHeader, body);
671 }
672
673 @MOVE
674 @Path("/{repoName}/{repoPath:.*}/")
675 public Response move(@PathParam("repoName") String repoName,
676 @PathParam("repoPath") String repoPath,
677 @HeaderParam(ExtHttpHeaders.DESTINATION) String destinationHeader,
678 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
679 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
680 @HeaderParam(ExtHttpHeaders.DEPTH) String depthHeader,
681 @HeaderParam(ExtHttpHeaders.OVERWRITE) String overwriteHeader,
682 @Context UriInfo uriInfo,
683 HierarchicalProperty body) {
684 try {
685 repoPath = convertRepoPath(repoPath, true);
686 } catch (PathNotFoundException exc) {
687 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
688 } catch (NoSuchWorkspaceException exc) {
689 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
690 } catch (Exception e) {
691 if (LOG.isWarnEnabled()) {
692 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
693 }
694 return Response.serverError().build();
695 }
696 Response response = super.move(repoName,
697 repoPath,
698 destinationHeader,
699 lockTokenHeader,
700 ifHeader,
701 depthHeader,
702 overwriteHeader,
703 uriInfo,
704 body);
705
706 if (response.getStatus() == HTTPStatus.CREATED) {
707 updateProperties(destinationHeader, repoName);
708 }
709 markTempFilesToHidden(repoPath);
710 return response;
711 }
712
713
714
715
716
717
718
719 private void updateProperties(String destinationHeader, String repoName) {
720 try {
721 URI dest = buildURI(destinationHeader);
722 String destPath = dest.getPath();
723 int repoIndex = destPath.indexOf(repoName);
724 destPath = normalizePath(repoIndex == -1 ? destPath : destPath.substring(repoIndex + repoName.length() + 1));
725 String destNodePath = path(destPath);
726 Node destNode = (Node) nodeFinder.getItem(workspaceName(destPath), path(normalizePath(destNodePath)), true);
727 String nodeName = Text.escapeIllegalJcrChars(destNode.getName());
728 destNode.setProperty("exo:name", nodeName);
729 destNode.setProperty("exo:title", nodeName);
730 if (!Utils.isFolder(destNode)) {
731 Node content = destNode.getNode("jcr:content");
732 String mimeType = mimeTypeResolver.getMimeType(nodeName);
733 content.setProperty("jcr:mimeType", mimeType);
734
735 ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class);
736 if (destNode.isNodeType("exo:datetime")) {
737 destNode.setProperty("exo:dateModified", new GregorianCalendar());
738 }
739 listenerService.broadcast(CmsService.POST_EDIT_CONTENT_EVENT, destNode.getParent(), destNode);
740 }
741 destNode.save();
742 } catch (Exception e) {
743 if (LOG.isWarnEnabled()) {
744 LOG.warn("Cannot change property of destNode" + destinationHeader, e);
745 }
746 }
747 }
748
749
750
751
752 private URI buildURI(String path) throws URISyntaxException {
753 try {
754 return new URI(path);
755 }
756 catch (URISyntaxException e) {
757 return new URI(TextUtil.escape(path, '%', true));
758 }
759 }
760
761
762
763
764 @MKCOL
765 @Path("/{repoName}/{repoPath:.*}/")
766 public Response mkcol(@PathParam("repoName") String repoName,
767 @PathParam("repoPath") String repoPath,
768 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
769 @HeaderParam(ExtHttpHeaders.IF) String ifHeader,
770 @HeaderParam(ExtHttpHeaders.CONTENT_NODETYPE) String nodeTypeHeader,
771 @HeaderParam(ExtHttpHeaders.CONTENT_MIXINTYPES) String mixinTypesHeader,
772 @Context UriInfo uriInfo) {
773 try {
774 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
775 Item item = nodeFinder.getItem(workspaceName(repoPath), LinkUtils.getParentPath(path(normalizePath(repoPath))), true);
776 repoPath =
777 item.getSession().getWorkspace().getName() + LinkUtils.createPath(item.getPath(),
778 LinkUtils.getItemName(path(repoPath)));
779 } catch (PathNotFoundException exc) {
780 return Response.status(HTTPStatus.CONFLICT).entity(exc.getMessage()).build();
781 } catch (NoSuchWorkspaceException exc) {
782 return Response.status(HTTPStatus.CONFLICT).entity(exc.getMessage()).build();
783 } catch (Exception e) {
784 if (LOG.isWarnEnabled()) {
785 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
786 }
787 return Response.serverError().build();
788 }
789 return super.mkcol(repoName,
790 repoPath,
791 lockTokenHeader,
792 ifHeader,
793 nodeTypeHeader,
794 mixinTypesHeader,
795 uriInfo);
796 }
797
798 @DELETE
799 @Path("/{repoName}/{repoPath:.*}/")
800 public Response delete(@PathParam("repoName") String repoName,
801 @PathParam("repoPath") String repoPath,
802 @HeaderParam(ExtHttpHeaders.LOCKTOKEN) String lockTokenHeader,
803 @HeaderParam(ExtHttpHeaders.IF) String ifHeader) {
804 Item item = null;
805 try {
806 repoName = repositoryService.getCurrentRepository().getConfiguration().getName();
807 repoPath = convertRepoPath(repoPath, false);
808
809 try {
810 item = nodeFinder.getItem(workspaceName(repoPath),
811 path(normalizePath(repoPath)),
812 true);
813 } catch (PathNotFoundException e) {
814 item = nodeFinder.getItem(workspaceName(repoPath),
815 path(Text.escapeIllegalJcrChars(repoPath)),
816 true);
817 }
818
819 } catch (PathNotFoundException exc) {
820 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
821 } catch (NoSuchWorkspaceException exc) {
822 return Response.status(HTTPStatus.NOT_FOUND).entity(exc.getMessage()).build();
823 } catch (Exception e) {
824 if (LOG.isWarnEnabled()) {
825 LOG.warn("Cannot find the item at " + repoName + "/" + repoPath, e);
826 }
827 return Response.serverError().build();
828 }
829
830 try {
831
832 Node node = (Node)item;
833 ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class);
834 ActivityCommonService activityService = WCMCoreUtils.getService(ActivityCommonService.class);
835 Node parent = node.getParent();
836 if (node.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
837 if (activityService.isBroadcastNTFileEvents(node)) {
838 listenerService.broadcast(ActivityCommonService.FILE_REMOVE_ACTIVITY, parent, node);
839 }
840 } else if(!WCMCoreUtils.isDocumentNodeType(node)){
841 Queue<Node> queue = new LinkedList<Node>();
842 queue.add(node);
843
844
845 Node tempNode = null;
846 try {
847 while (!queue.isEmpty()) {
848 tempNode = queue.poll();
849 if (WCMCoreUtils.isDocumentNodeType(tempNode)
850 || tempNode.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
851 listenerService.broadcast(ActivityCommonService.FILE_REMOVE_ACTIVITY, tempNode.getParent(), tempNode);
852 } else {
853 for (NodeIterator iter = tempNode.getNodes(); iter.hasNext(); ) {
854 Node childNode = iter.nextNode();
855 if(WCMCoreUtils.isDocumentNodeType(childNode) || childNode.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)
856 || childNode.isNodeType(NodetypeConstant.NT_FOLDER))
857 queue.add(childNode);
858 }
859 }
860 }
861 } catch (Exception e) {
862 if (LOG.isWarnEnabled()) {
863 LOG.warn(e.getMessage());
864 }
865 }
866 }
867
868 Utils.removeSymlinks(node);
869 } catch(Exception ex) {
870 if (LOG.isWarnEnabled()) {
871 LOG.warn(ex.getMessage());
872 }
873 }
874 return super.delete(repoName, repoPath, lockTokenHeader, ifHeader);
875 }
876
877 private String convertRepoPath(String repoPath, boolean giveTarget) throws Exception{
878 try {
879 Item item = nodeFinder.getItem(workspaceName(repoPath), path(normalizePath(repoPath)), giveTarget);
880 return item.getSession().getWorkspace().getName() + item.getPath();
881 } catch (PathNotFoundException e) {
882 Item item = nodeFinder.getItem(workspaceName(repoPath), path(Text.escapeIllegalJcrChars(repoPath)), giveTarget);
883 return item.getSession().getWorkspace().getName() + item.getPath();
884 }
885 }
886
887
888
889
890
891 private boolean markTempFilesToHidden(String repoPath){
892 if(StringUtils.isBlank(repoPath)) return false;
893 String tempNodeFolder = ".TemporaryItems";
894 String tempNodeFileChild = "._folders.501";
895 String tempNodeFile = "._.TemporaryItems";
896 String txtTempRegex = "/._";
897 try {
898 String txtTemp = repoPath.substring(repoPath.lastIndexOf("/"), repoPath.length());
899 boolean isTxtTemp = txtTemp.startsWith(txtTempRegex)?true:false;
900 if(repoPath.contains(tempNodeFile) || isTxtTemp){
901 Node _tempNodeFile = (Node)nodeFinder.getItem(workspaceName(repoPath), path(repoPath), true);
902 _tempNodeFile.remove();
903 _tempNodeFile.getSession().save();
904 return false;
905 }else if(repoPath.contains(tempNodeFolder)) {
906 String currentNodePath = repoPath.substring(0, repoPath.indexOf(tempNodeFolder));
907 Node currentNode = (Node)nodeFinder.getItem(workspaceName(repoPath), path(currentNodePath), true);
908
909 if(currentNode.hasNode(tempNodeFolder)){
910 Node _tmpFolderNode = currentNode.getNode(tempNodeFolder);
911 if(_tmpFolderNode.canAddMixin(NodetypeConstant.EXO_HIDDENABLE)) _tmpFolderNode.addMixin(NodetypeConstant.EXO_HIDDENABLE);
912 if (_tmpFolderNode.hasNode(tempNodeFileChild)){
913 Node _tempNodeFileChild = _tmpFolderNode.getNode(tempNodeFileChild);
914 _tempNodeFileChild.remove();
915 }
916 _tmpFolderNode.save();
917 }
918 return false;
919 }
920 }catch(RepositoryException ex){
921 if (LOG.isWarnEnabled()) {
922 LOG.warn("The hidden temp files has been ignored " + ex.getMessage());
923 }
924 }
925 return true;
926 }
927
928 }