1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.imagegallery.webdav;
24  
25  import com.liferay.documentlibrary.DuplicateFileException;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.log.Log;
29  import com.liferay.portal.kernel.log.LogFactoryUtil;
30  import com.liferay.portal.kernel.util.FileUtil;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  import com.liferay.portal.security.auth.PrincipalException;
35  import com.liferay.portal.service.ServiceContext;
36  import com.liferay.portal.util.ContentTypeUtil;
37  import com.liferay.portal.webdav.BaseResourceImpl;
38  import com.liferay.portal.webdav.BaseWebDAVStorageImpl;
39  import com.liferay.portal.webdav.Resource;
40  import com.liferay.portal.webdav.Status;
41  import com.liferay.portal.webdav.WebDAVException;
42  import com.liferay.portal.webdav.WebDAVRequest;
43  import com.liferay.portal.webdav.WebDAVUtil;
44  import com.liferay.portlet.imagegallery.DuplicateFolderNameException;
45  import com.liferay.portlet.imagegallery.NoSuchFolderException;
46  import com.liferay.portlet.imagegallery.NoSuchImageException;
47  import com.liferay.portlet.imagegallery.model.IGFolder;
48  import com.liferay.portlet.imagegallery.model.IGImage;
49  import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
50  import com.liferay.portlet.imagegallery.service.IGFolderServiceUtil;
51  import com.liferay.portlet.imagegallery.service.IGImageServiceUtil;
52  import com.liferay.portlet.tags.service.TagsEntryLocalServiceUtil;
53  
54  import java.io.File;
55  import java.io.InputStream;
56  
57  import java.util.ArrayList;
58  import java.util.List;
59  
60  import javax.servlet.http.HttpServletRequest;
61  import javax.servlet.http.HttpServletResponse;
62  
63  /**
64   * <a href="IGWebDAVStorageImpl.java.html"><b><i>View Source</i></b></a>
65   *
66   * @author Alexander Chow
67   *
68   */
69  public class IGWebDAVStorageImpl extends BaseWebDAVStorageImpl {
70  
71      public int copyCollectionResource(
72              WebDAVRequest webDavRequest, Resource resource, String destination,
73              boolean overwrite, long depth)
74          throws WebDAVException {
75  
76          try {
77              String[] destinationArray = WebDAVUtil.getPathArray(
78                  destination, true);
79  
80              long parentFolderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
81  
82              try {
83                  parentFolderId = getParentFolderId(destinationArray);
84              }
85              catch (NoSuchFolderException nsfe) {
86                  return HttpServletResponse.SC_CONFLICT;
87              }
88  
89              IGFolder folder = (IGFolder)resource.getModel();
90  
91              long groupId = WebDAVUtil.getGroupId(destination);
92              String name = WebDAVUtil.getResourceName(destinationArray);
93              String description = folder.getDescription();
94              boolean addCommunityPermissions = true;
95              boolean addGuestPermissions = true;
96  
97              int status = HttpServletResponse.SC_CREATED;
98  
99              if (overwrite) {
100                 if (deleteResource(groupId, parentFolderId, name)) {
101                     status = HttpServletResponse.SC_NO_CONTENT;
102                 }
103             }
104 
105             ServiceContext serviceContext = new ServiceContext();
106 
107             serviceContext.setAddCommunityPermissions(addCommunityPermissions);
108             serviceContext.setAddGuestPermissions(addGuestPermissions);
109             serviceContext.setScopeGroupId(groupId);
110 
111             if (depth == 0) {
112                 IGFolderServiceUtil.addFolder(
113                     parentFolderId, name, description, serviceContext);
114             }
115             else {
116                 IGFolderServiceUtil.copyFolder(
117                     folder.getFolderId(), parentFolderId, name, description,
118                     serviceContext);
119             }
120 
121             return status;
122         }
123         catch (DuplicateFolderNameException dfne) {
124             return HttpServletResponse.SC_PRECONDITION_FAILED;
125         }
126         catch (PrincipalException pe) {
127             return HttpServletResponse.SC_FORBIDDEN;
128         }
129         catch (Exception e) {
130             throw new WebDAVException(e);
131         }
132     }
133 
134     public int copySimpleResource(
135             WebDAVRequest webDavRequest, Resource resource, String destination,
136             boolean overwrite)
137         throws WebDAVException {
138 
139         File file = null;
140 
141         try {
142             String[] destinationArray = WebDAVUtil.getPathArray(
143                 destination, true);
144 
145             long parentFolderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
146 
147             try {
148                 parentFolderId = getParentFolderId(destinationArray);
149             }
150             catch (NoSuchFolderException nsfe) {
151                 return HttpServletResponse.SC_CONFLICT;
152             }
153 
154             IGImage image = (IGImage)resource.getModel();
155 
156             long groupId = WebDAVUtil.getGroupId(destination);
157             String name = WebDAVUtil.getResourceName(destinationArray);
158             String description = image.getDescription();
159             String contentType = ContentTypeUtil.getContentType(
160                 image.getNameWithExtension());
161 
162             file = FileUtil.createTempFile(image.getImageType());
163 
164             InputStream is = resource.getContentAsStream();
165 
166             FileUtil.write(file, is);
167 
168             ServiceContext serviceContext = new ServiceContext();
169 
170             serviceContext.setAddCommunityPermissions(true);
171             serviceContext.setAddGuestPermissions(true);
172 
173             int status = HttpServletResponse.SC_CREATED;
174 
175             if (overwrite) {
176                 if (deleteResource(groupId, parentFolderId, name)) {
177                     status = HttpServletResponse.SC_NO_CONTENT;
178                 }
179             }
180 
181             IGImageServiceUtil.addImage(
182                 parentFolderId, name, description, file, contentType,
183                 serviceContext);
184 
185             return status;
186         }
187         catch (DuplicateFolderNameException dfne) {
188             return HttpServletResponse.SC_PRECONDITION_FAILED;
189         }
190         catch (DuplicateFileException dfe) {
191             return HttpServletResponse.SC_PRECONDITION_FAILED;
192         }
193         catch (PrincipalException pe) {
194             return HttpServletResponse.SC_FORBIDDEN;
195         }
196         catch (Exception e) {
197             throw new WebDAVException(e);
198         }
199         finally {
200             if (file != null) {
201                 file.delete();
202             }
203         }
204     }
205 
206     public int deleteResource(WebDAVRequest webDavRequest)
207         throws WebDAVException {
208 
209         try {
210             Resource resource = getResource(webDavRequest);
211 
212             if (resource == null) {
213                 return HttpServletResponse.SC_NOT_FOUND;
214             }
215 
216             Object model = resource.getModel();
217 
218             if (model instanceof IGFolder) {
219                 IGFolder folder = (IGFolder)model;
220 
221                 IGFolderServiceUtil.deleteFolder(folder.getFolderId());
222             }
223             else {
224                 IGImage image = (IGImage)model;
225 
226                 IGImageServiceUtil.deleteImage(image.getImageId());
227             }
228 
229             return HttpServletResponse.SC_NO_CONTENT;
230         }
231         catch (PrincipalException pe) {
232             return HttpServletResponse.SC_FORBIDDEN;
233         }
234         catch (Exception e) {
235             throw new WebDAVException(e);
236         }
237     }
238 
239     public Resource getResource(WebDAVRequest webDavRequest)
240         throws WebDAVException {
241 
242         try {
243             String[] pathArray = webDavRequest.getPathArray();
244 
245             long parentFolderId = getParentFolderId(pathArray);
246             String name = WebDAVUtil.getResourceName(pathArray);
247 
248             if (Validator.isNull(name)) {
249                 String path = getRootPath() + webDavRequest.getPath();
250 
251                 return new BaseResourceImpl(path, StringPool.BLANK, getToken());
252             }
253 
254             try {
255                 IGFolder folder = IGFolderServiceUtil.getFolder(
256                     webDavRequest.getGroupId(), parentFolderId, name);
257 
258                 if ((folder.getParentFolderId() != parentFolderId) ||
259                     (webDavRequest.getGroupId() != folder.getGroupId())) {
260 
261                     throw new NoSuchFolderException();
262                 }
263 
264                 return toResource(webDavRequest, folder, false);
265             }
266             catch (NoSuchFolderException nsfe) {
267                 try {
268                     IGImage image =
269                         IGImageServiceUtil.
270                             getImageByFolderIdAndNameWithExtension(
271                                 parentFolderId, name);
272 
273                     return toResource(webDavRequest, image, false);
274                 }
275                 catch (NoSuchImageException nsie) {
276                     return null;
277                 }
278             }
279         }
280         catch (Exception e) {
281             throw new WebDAVException(e);
282         }
283     }
284 
285     public List<Resource> getResources(WebDAVRequest webDavRequest)
286         throws WebDAVException {
287 
288         try {
289             long folderId = getFolderId(webDavRequest.getPathArray());
290 
291             List<Resource> folders = getFolders(webDavRequest, folderId);
292             List<Resource> images = getImages(webDavRequest, folderId);
293 
294             List<Resource> resources = new ArrayList<Resource>(
295                 folders.size() + images.size());
296 
297             resources.addAll(folders);
298             resources.addAll(images);
299 
300             return resources;
301         }
302         catch (Exception e) {
303             throw new WebDAVException(e);
304         }
305     }
306 
307     public Status makeCollection(WebDAVRequest webDavRequest)
308         throws WebDAVException {
309 
310         try {
311             HttpServletRequest request = webDavRequest.getHttpServletRequest();
312 
313             if (request.getContentLength() > 0) {
314                 return new Status(
315                     HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
316             }
317 
318             String[] pathArray = webDavRequest.getPathArray();
319 
320             long parentFolderId = getParentFolderId(pathArray);
321             String name = WebDAVUtil.getResourceName(pathArray);
322             String description = StringPool.BLANK;
323 
324             ServiceContext serviceContext = new ServiceContext();
325 
326             serviceContext.setAddCommunityPermissions(true);
327             serviceContext.setAddGuestPermissions(true);
328             serviceContext.setPlid(getPlid(webDavRequest.getGroupId()));
329             serviceContext.setScopeGroupId(webDavRequest.getGroupId());
330 
331             IGFolderServiceUtil.addFolder(
332                 parentFolderId, name, description, serviceContext);
333 
334             String location = StringUtil.merge(pathArray, StringPool.SLASH);
335 
336             return new Status(location, HttpServletResponse.SC_CREATED);
337         }
338         catch (DuplicateFolderNameException dfne) {
339             return new Status(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
340         }
341         catch (NoSuchFolderException nsfe) {
342             return new Status(HttpServletResponse.SC_CONFLICT);
343         }
344         catch (PrincipalException pe) {
345             return new Status(HttpServletResponse.SC_FORBIDDEN);
346         }
347         catch (Exception e) {
348             throw new WebDAVException(e);
349         }
350     }
351 
352     public int moveCollectionResource(
353             WebDAVRequest webDavRequest, Resource resource, String destination,
354             boolean overwrite)
355         throws WebDAVException {
356 
357         try {
358             String[] destinationArray = WebDAVUtil.getPathArray(
359                 destination, true);
360 
361             IGFolder folder = (IGFolder)resource.getModel();
362 
363             long groupId = WebDAVUtil.getGroupId(destinationArray);
364             long folderId = folder.getFolderId();
365             long parentFolderId = getParentFolderId(destinationArray);
366             String name = WebDAVUtil.getResourceName(destinationArray);
367             String description = folder.getDescription();
368 
369             ServiceContext serviceContext = new ServiceContext();
370 
371             int status = HttpServletResponse.SC_CREATED;
372 
373             if (overwrite) {
374                 if (deleteResource(groupId, parentFolderId, name)) {
375                     status = HttpServletResponse.SC_NO_CONTENT;
376                 }
377             }
378 
379             IGFolderServiceUtil.updateFolder(
380                 folderId, parentFolderId, name, description, false,
381                 serviceContext);
382 
383             return status;
384         }
385         catch (PrincipalException pe) {
386             return HttpServletResponse.SC_FORBIDDEN;
387         }
388         catch (DuplicateFolderNameException dfne) {
389             return HttpServletResponse.SC_PRECONDITION_FAILED;
390         }
391         catch (Exception e) {
392             throw new WebDAVException(e);
393         }
394     }
395 
396     public int moveSimpleResource(
397             WebDAVRequest webDavRequest, Resource resource, String destination,
398             boolean overwrite)
399         throws WebDAVException {
400 
401         try {
402             String[] destinationArray = WebDAVUtil.getPathArray(
403                 destination, true);
404 
405             IGImage image = (IGImage)resource.getModel();
406 
407             long groupId = WebDAVUtil.getGroupId(destinationArray);
408             long parentFolderId = getParentFolderId(destinationArray);
409             String name = WebDAVUtil.getResourceName(destinationArray);
410             String description = image.getDescription();
411             File file = null;
412             String contentType = null;
413 
414             ServiceContext serviceContext = new ServiceContext();
415 
416             int status = HttpServletResponse.SC_CREATED;
417 
418             if (overwrite) {
419                 if (deleteResource(groupId, parentFolderId, name)) {
420                     status = HttpServletResponse.SC_NO_CONTENT;
421                 }
422             }
423 
424             IGImageServiceUtil.updateImage(
425                 image.getImageId(), parentFolderId, name, description, file,
426                 contentType, serviceContext);
427 
428             return status;
429         }
430         catch (PrincipalException pe) {
431             return HttpServletResponse.SC_FORBIDDEN;
432         }
433         catch (DuplicateFileException dfe) {
434             return HttpServletResponse.SC_PRECONDITION_FAILED;
435         }
436         catch (DuplicateFolderNameException dfne) {
437             return HttpServletResponse.SC_PRECONDITION_FAILED;
438         }
439         catch (Exception e) {
440             throw new WebDAVException(e);
441         }
442     }
443 
444     public int putResource(WebDAVRequest webDavRequest) throws WebDAVException {
445         File file = null;
446 
447         try {
448             HttpServletRequest request = webDavRequest.getHttpServletRequest();
449 
450             String[] pathArray = webDavRequest.getPathArray();
451 
452             long parentFolderId = getParentFolderId(pathArray);
453             String name = WebDAVUtil.getResourceName(pathArray);
454             String description = StringPool.BLANK;
455 
456             file = FileUtil.createTempFile(FileUtil.getExtension(name));
457 
458             FileUtil.write(file, request.getInputStream());
459 
460             String contentType = ContentTypeUtil.getContentType(name);
461 
462             ServiceContext serviceContext = new ServiceContext();
463 
464             serviceContext.setAddCommunityPermissions(true);
465             serviceContext.setAddGuestPermissions(true);
466 
467             try {
468                 IGImage image =
469                     IGImageServiceUtil.getImageByFolderIdAndNameWithExtension(
470                         parentFolderId, name);
471 
472                 long imageId = image.getImageId();
473 
474                 description = image.getDescription();
475                 String[] tagsEntries = TagsEntryLocalServiceUtil.getEntryNames(
476                     IGImage.class.getName(), imageId);
477 
478                 serviceContext.setTagsEntries(tagsEntries);
479 
480                 IGImageServiceUtil.updateImage(
481                     imageId, parentFolderId, name, description, file,
482                     contentType, serviceContext);
483             }
484             catch (NoSuchImageException nsie) {
485                 IGImageServiceUtil.addImage(
486                     parentFolderId, name, description, file, contentType,
487                     serviceContext);
488             }
489 
490             return HttpServletResponse.SC_CREATED;
491         }
492         catch (PrincipalException pe) {
493             return HttpServletResponse.SC_FORBIDDEN;
494         }
495         catch (PortalException pe) {
496             if (_log.isWarnEnabled()) {
497                 _log.warn(pe, pe);
498             }
499 
500             return HttpServletResponse.SC_CONFLICT;
501         }
502         catch (Exception e) {
503             throw new WebDAVException(e);
504         }
505         finally {
506             if (file != null) {
507                 file.delete();
508             }
509         }
510     }
511 
512     protected boolean deleteResource(
513             long groupId, long parentFolderId, String name)
514         throws PortalException, SystemException {
515 
516         try {
517             IGFolder folder = IGFolderServiceUtil.getFolder(
518                 groupId, parentFolderId, name);
519 
520             IGFolderServiceUtil.deleteFolder(folder.getFolderId());
521 
522             return true;
523         }
524         catch (NoSuchFolderException nsfe) {
525             if (name.indexOf(StringPool.PERIOD) == -1) {
526                 return false;
527             }
528 
529             try {
530                 IGImageServiceUtil.deleteImageByFolderIdAndNameWithExtension(
531                     parentFolderId, name);
532 
533                 return true;
534             }
535             catch (NoSuchImageException nsie) {
536             }
537         }
538 
539         return false;
540     }
541 
542     protected List<Resource> getFolders(
543             WebDAVRequest webDavRequest, long parentFolderId)
544         throws Exception {
545 
546         List<Resource> resources = new ArrayList<Resource>();
547 
548         long groupId = webDavRequest.getGroupId();
549 
550         List<IGFolder> folders = IGFolderServiceUtil.getFolders(
551             groupId, parentFolderId);
552 
553         for (IGFolder folder : folders) {
554             Resource resource = toResource(webDavRequest, folder, true);
555 
556             resources.add(resource);
557         }
558 
559         return resources;
560     }
561 
562     protected List<Resource> getImages(
563             WebDAVRequest webDavRequest, long parentFolderId)
564         throws Exception {
565 
566         List<Resource> resources = new ArrayList<Resource>();
567 
568         List<IGImage> images = IGImageServiceUtil.getImages(parentFolderId);
569 
570         for (IGImage image : images) {
571             Resource resource = toResource(webDavRequest, image, true);
572 
573             resources.add(resource);
574         }
575 
576         return resources;
577     }
578 
579     protected long getFolderId(String[] pathArray) throws Exception {
580         return getFolderId(pathArray, false);
581     }
582 
583     protected long getFolderId(String[] pathArray, boolean parent)
584         throws Exception {
585 
586         long folderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
587 
588         if (pathArray.length <= 2) {
589             return folderId;
590         }
591         else {
592             long groupId = WebDAVUtil.getGroupId(pathArray);
593 
594             int x = pathArray.length;
595 
596             if (parent) {
597                 x--;
598             }
599 
600             for (int i = 3; i < x; i++) {
601                 String name = pathArray[i];
602 
603                 IGFolder folder = IGFolderServiceUtil.getFolder(
604                     groupId, folderId, name);
605 
606                 if (groupId == folder.getGroupId()) {
607                     folderId = folder.getFolderId();
608                 }
609             }
610         }
611 
612         return folderId;
613     }
614 
615     protected long getParentFolderId(String[] pathArray) throws Exception {
616         return getFolderId(pathArray, true);
617     }
618 
619     protected Resource toResource(
620         WebDAVRequest webDavRequest, IGImage image, boolean appendPath) {
621 
622         String parentPath = getRootPath() + webDavRequest.getPath();
623         String name = StringPool.BLANK;
624 
625         if (appendPath) {
626             name = image.getNameWithExtension();
627         }
628 
629         return new IGImageResourceImpl(image, parentPath, name);
630     }
631 
632     protected Resource toResource(
633         WebDAVRequest webDavRequest, IGFolder folder, boolean appendPath) {
634 
635         String parentPath = getRootPath() + webDavRequest.getPath();
636         String name = StringPool.BLANK;
637 
638         if (appendPath) {
639             name = folder.getName();
640         }
641 
642         Resource resource = new BaseResourceImpl(
643             parentPath, name, folder.getName(), folder.getCreateDate(),
644             folder.getModifiedDate());
645 
646         resource.setModel(folder);
647         resource.setClassName(IGFolder.class.getName());
648         resource.setPrimaryKey(folder.getPrimaryKey());
649 
650         return resource;
651     }
652 
653     private static Log _log = LogFactoryUtil.getLog(IGWebDAVStorageImpl.class);
654 
655 }