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.MimeTypesUtil;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.security.auth.PrincipalException;
36  import com.liferay.portal.service.ServiceContext;
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  public class IGWebDAVStorageImpl extends BaseWebDAVStorageImpl {
69  
70      public int copyCollectionResource(
71              WebDAVRequest webDavRequest, Resource resource, String destination,
72              boolean overwrite, long depth)
73          throws WebDAVException {
74  
75          try {
76              String[] destinationArray = WebDAVUtil.getPathArray(
77                  destination, true);
78  
79              long parentFolderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
80  
81              try {
82                  parentFolderId = getParentFolderId(destinationArray);
83              }
84              catch (NoSuchFolderException nsfe) {
85                  return HttpServletResponse.SC_CONFLICT;
86              }
87  
88              IGFolder folder = (IGFolder)resource.getModel();
89  
90              long groupId = WebDAVUtil.getGroupId(destination);
91              String name = WebDAVUtil.getResourceName(destinationArray);
92              String description = folder.getDescription();
93  
94              int status = HttpServletResponse.SC_CREATED;
95  
96              if (overwrite) {
97                  if (deleteResource(groupId, parentFolderId, name)) {
98                      status = HttpServletResponse.SC_NO_CONTENT;
99                  }
100             }
101 
102             ServiceContext serviceContext = new ServiceContext();
103 
104             serviceContext.setAddCommunityPermissions(
105                 isAddCommunityPermissions(groupId));
106             serviceContext.setAddGuestPermissions(true);
107             serviceContext.setScopeGroupId(groupId);
108 
109             if (depth == 0) {
110                 IGFolderServiceUtil.addFolder(
111                     parentFolderId, name, description, serviceContext);
112             }
113             else {
114                 IGFolderServiceUtil.copyFolder(
115                     folder.getFolderId(), parentFolderId, name, description,
116                     serviceContext);
117             }
118 
119             return status;
120         }
121         catch (DuplicateFolderNameException dfne) {
122             return HttpServletResponse.SC_PRECONDITION_FAILED;
123         }
124         catch (PrincipalException pe) {
125             return HttpServletResponse.SC_FORBIDDEN;
126         }
127         catch (Exception e) {
128             throw new WebDAVException(e);
129         }
130     }
131 
132     public int copySimpleResource(
133             WebDAVRequest webDavRequest, Resource resource, String destination,
134             boolean overwrite)
135         throws WebDAVException {
136 
137         File file = null;
138 
139         try {
140             String[] destinationArray = WebDAVUtil.getPathArray(
141                 destination, true);
142 
143             long parentFolderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
144 
145             try {
146                 parentFolderId = getParentFolderId(destinationArray);
147             }
148             catch (NoSuchFolderException nsfe) {
149                 return HttpServletResponse.SC_CONFLICT;
150             }
151 
152             IGImage image = (IGImage)resource.getModel();
153 
154             long groupId = WebDAVUtil.getGroupId(destination);
155             String name = WebDAVUtil.getResourceName(destinationArray);
156             String description = image.getDescription();
157             String contentType = MimeTypesUtil.getContentType(
158                 image.getNameWithExtension());
159 
160             file = FileUtil.createTempFile(image.getImageType());
161 
162             InputStream is = resource.getContentAsStream();
163 
164             FileUtil.write(file, is);
165 
166             ServiceContext serviceContext = new ServiceContext();
167 
168             serviceContext.setAddCommunityPermissions(
169                 isAddCommunityPermissions(groupId));
170             serviceContext.setAddGuestPermissions(true);
171 
172             int status = HttpServletResponse.SC_CREATED;
173 
174             if (overwrite) {
175                 if (deleteResource(groupId, parentFolderId, name)) {
176                     status = HttpServletResponse.SC_NO_CONTENT;
177                 }
178             }
179 
180             IGImageServiceUtil.addImage(
181                 parentFolderId, name, description, file, contentType,
182                 serviceContext);
183 
184             return status;
185         }
186         catch (DuplicateFolderNameException dfne) {
187             return HttpServletResponse.SC_PRECONDITION_FAILED;
188         }
189         catch (DuplicateFileException dfe) {
190             return HttpServletResponse.SC_PRECONDITION_FAILED;
191         }
192         catch (PrincipalException pe) {
193             return HttpServletResponse.SC_FORBIDDEN;
194         }
195         catch (Exception e) {
196             throw new WebDAVException(e);
197         }
198         finally {
199             if (file != null) {
200                 file.delete();
201             }
202         }
203     }
204 
205     public int deleteResource(WebDAVRequest webDavRequest)
206         throws WebDAVException {
207 
208         try {
209             Resource resource = getResource(webDavRequest);
210 
211             if (resource == null) {
212                 return HttpServletResponse.SC_NOT_FOUND;
213             }
214 
215             Object model = resource.getModel();
216 
217             if (model instanceof IGFolder) {
218                 IGFolder folder = (IGFolder)model;
219 
220                 IGFolderServiceUtil.deleteFolder(folder.getFolderId());
221             }
222             else {
223                 IGImage image = (IGImage)model;
224 
225                 IGImageServiceUtil.deleteImage(image.getImageId());
226             }
227 
228             return HttpServletResponse.SC_NO_CONTENT;
229         }
230         catch (PrincipalException pe) {
231             return HttpServletResponse.SC_FORBIDDEN;
232         }
233         catch (Exception e) {
234             throw new WebDAVException(e);
235         }
236     }
237 
238     public Resource getResource(WebDAVRequest webDavRequest)
239         throws WebDAVException {
240 
241         try {
242             String[] pathArray = webDavRequest.getPathArray();
243 
244             long parentFolderId = getParentFolderId(pathArray);
245             String name = WebDAVUtil.getResourceName(pathArray);
246 
247             if (Validator.isNull(name)) {
248                 String path = getRootPath() + webDavRequest.getPath();
249 
250                 return new BaseResourceImpl(path, StringPool.BLANK, getToken());
251             }
252 
253             try {
254                 IGFolder folder = IGFolderServiceUtil.getFolder(
255                     webDavRequest.getGroupId(), parentFolderId, name);
256 
257                 if ((folder.getParentFolderId() != parentFolderId) ||
258                     (webDavRequest.getGroupId() != folder.getGroupId())) {
259 
260                     throw new NoSuchFolderException();
261                 }
262 
263                 return toResource(webDavRequest, folder, false);
264             }
265             catch (NoSuchFolderException nsfe) {
266                 try {
267                     IGImage image =
268                         IGImageServiceUtil.
269                             getImageByFolderIdAndNameWithExtension(
270                                 parentFolderId, name);
271 
272                     return toResource(webDavRequest, image, false);
273                 }
274                 catch (NoSuchImageException nsie) {
275                     return null;
276                 }
277             }
278         }
279         catch (Exception e) {
280             throw new WebDAVException(e);
281         }
282     }
283 
284     public List<Resource> getResources(WebDAVRequest webDavRequest)
285         throws WebDAVException {
286 
287         try {
288             long folderId = getFolderId(webDavRequest.getPathArray());
289 
290             List<Resource> folders = getFolders(webDavRequest, folderId);
291             List<Resource> images = getImages(webDavRequest, folderId);
292 
293             List<Resource> resources = new ArrayList<Resource>(
294                 folders.size() + images.size());
295 
296             resources.addAll(folders);
297             resources.addAll(images);
298 
299             return resources;
300         }
301         catch (Exception e) {
302             throw new WebDAVException(e);
303         }
304     }
305 
306     public Status makeCollection(WebDAVRequest webDavRequest)
307         throws WebDAVException {
308 
309         try {
310             HttpServletRequest request = webDavRequest.getHttpServletRequest();
311 
312             if (request.getContentLength() > 0) {
313                 return new Status(
314                     HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
315             }
316 
317             String[] pathArray = webDavRequest.getPathArray();
318 
319             long groupId = webDavRequest.getGroupId();
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(
327                 isAddCommunityPermissions(groupId));
328             serviceContext.setAddGuestPermissions(true);
329             serviceContext.setPlid(getPlid(webDavRequest.getGroupId()));
330             serviceContext.setScopeGroupId(webDavRequest.getGroupId());
331 
332             IGFolderServiceUtil.addFolder(
333                 parentFolderId, name, description, serviceContext);
334 
335             String location = StringUtil.merge(pathArray, StringPool.SLASH);
336 
337             return new Status(location, HttpServletResponse.SC_CREATED);
338         }
339         catch (DuplicateFolderNameException dfne) {
340             return new Status(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
341         }
342         catch (NoSuchFolderException nsfe) {
343             return new Status(HttpServletResponse.SC_CONFLICT);
344         }
345         catch (PrincipalException pe) {
346             return new Status(HttpServletResponse.SC_FORBIDDEN);
347         }
348         catch (Exception e) {
349             throw new WebDAVException(e);
350         }
351     }
352 
353     public int moveCollectionResource(
354             WebDAVRequest webDavRequest, Resource resource, String destination,
355             boolean overwrite)
356         throws WebDAVException {
357 
358         try {
359             String[] destinationArray = WebDAVUtil.getPathArray(
360                 destination, true);
361 
362             IGFolder folder = (IGFolder)resource.getModel();
363 
364             long groupId = WebDAVUtil.getGroupId(destinationArray);
365             long folderId = folder.getFolderId();
366             long parentFolderId = getParentFolderId(destinationArray);
367             String name = WebDAVUtil.getResourceName(destinationArray);
368             String description = folder.getDescription();
369 
370             ServiceContext serviceContext = new ServiceContext();
371 
372             int status = HttpServletResponse.SC_CREATED;
373 
374             if (overwrite) {
375                 if (deleteResource(groupId, parentFolderId, name)) {
376                     status = HttpServletResponse.SC_NO_CONTENT;
377                 }
378             }
379 
380             IGFolderServiceUtil.updateFolder(
381                 folderId, parentFolderId, name, description, false,
382                 serviceContext);
383 
384             return status;
385         }
386         catch (PrincipalException pe) {
387             return HttpServletResponse.SC_FORBIDDEN;
388         }
389         catch (DuplicateFolderNameException dfne) {
390             return HttpServletResponse.SC_PRECONDITION_FAILED;
391         }
392         catch (Exception e) {
393             throw new WebDAVException(e);
394         }
395     }
396 
397     public int moveSimpleResource(
398             WebDAVRequest webDavRequest, Resource resource, String destination,
399             boolean overwrite)
400         throws WebDAVException {
401 
402         try {
403             String[] destinationArray = WebDAVUtil.getPathArray(
404                 destination, true);
405 
406             IGImage image = (IGImage)resource.getModel();
407 
408             long groupId = WebDAVUtil.getGroupId(destinationArray);
409             long parentFolderId = getParentFolderId(destinationArray);
410             String name = WebDAVUtil.getResourceName(destinationArray);
411             String description = image.getDescription();
412             File file = null;
413             String contentType = null;
414 
415             ServiceContext serviceContext = new ServiceContext();
416 
417             int status = HttpServletResponse.SC_CREATED;
418 
419             if (overwrite) {
420                 if (deleteResource(groupId, parentFolderId, name)) {
421                     status = HttpServletResponse.SC_NO_CONTENT;
422                 }
423             }
424 
425             IGImageServiceUtil.updateImage(
426                 image.getImageId(), parentFolderId, name, description, file,
427                 contentType, serviceContext);
428 
429             return status;
430         }
431         catch (PrincipalException pe) {
432             return HttpServletResponse.SC_FORBIDDEN;
433         }
434         catch (DuplicateFileException dfe) {
435             return HttpServletResponse.SC_PRECONDITION_FAILED;
436         }
437         catch (DuplicateFolderNameException dfne) {
438             return HttpServletResponse.SC_PRECONDITION_FAILED;
439         }
440         catch (Exception e) {
441             throw new WebDAVException(e);
442         }
443     }
444 
445     public int putResource(WebDAVRequest webDavRequest) throws WebDAVException {
446         File file = null;
447 
448         try {
449             HttpServletRequest request = webDavRequest.getHttpServletRequest();
450 
451             String[] pathArray = webDavRequest.getPathArray();
452 
453             long groupId = webDavRequest.getGroupId();
454             long parentFolderId = getParentFolderId(pathArray);
455             String name = WebDAVUtil.getResourceName(pathArray);
456             String description = StringPool.BLANK;
457 
458             file = FileUtil.createTempFile(FileUtil.getExtension(name));
459 
460             FileUtil.write(file, request.getInputStream());
461 
462             String contentType = MimeTypesUtil.getContentType(name);
463 
464             ServiceContext serviceContext = new ServiceContext();
465 
466             serviceContext.setAddCommunityPermissions(
467                 isAddCommunityPermissions(groupId));
468             serviceContext.setAddGuestPermissions(true);
469 
470             try {
471                 IGImage image =
472                     IGImageServiceUtil.getImageByFolderIdAndNameWithExtension(
473                         parentFolderId, name);
474 
475                 long imageId = image.getImageId();
476 
477                 description = image.getDescription();
478                 String[] tagsEntries = TagsEntryLocalServiceUtil.getEntryNames(
479                     IGImage.class.getName(), imageId);
480 
481                 serviceContext.setTagsEntries(tagsEntries);
482 
483                 IGImageServiceUtil.updateImage(
484                     imageId, parentFolderId, name, description, file,
485                     contentType, serviceContext);
486             }
487             catch (NoSuchImageException nsie) {
488                 IGImageServiceUtil.addImage(
489                     parentFolderId, name, description, file, contentType,
490                     serviceContext);
491             }
492 
493             return HttpServletResponse.SC_CREATED;
494         }
495         catch (PrincipalException pe) {
496             return HttpServletResponse.SC_FORBIDDEN;
497         }
498         catch (PortalException pe) {
499             if (_log.isWarnEnabled()) {
500                 _log.warn(pe, pe);
501             }
502 
503             return HttpServletResponse.SC_CONFLICT;
504         }
505         catch (Exception e) {
506             throw new WebDAVException(e);
507         }
508         finally {
509             if (file != null) {
510                 file.delete();
511             }
512         }
513     }
514 
515     protected boolean deleteResource(
516             long groupId, long parentFolderId, String name)
517         throws PortalException, SystemException {
518 
519         try {
520             IGFolder folder = IGFolderServiceUtil.getFolder(
521                 groupId, parentFolderId, name);
522 
523             IGFolderServiceUtil.deleteFolder(folder.getFolderId());
524 
525             return true;
526         }
527         catch (NoSuchFolderException nsfe) {
528             if (name.indexOf(StringPool.PERIOD) == -1) {
529                 return false;
530             }
531 
532             try {
533                 IGImageServiceUtil.deleteImageByFolderIdAndNameWithExtension(
534                     parentFolderId, name);
535 
536                 return true;
537             }
538             catch (NoSuchImageException nsie) {
539             }
540         }
541 
542         return false;
543     }
544 
545     protected List<Resource> getFolders(
546             WebDAVRequest webDavRequest, long parentFolderId)
547         throws Exception {
548 
549         List<Resource> resources = new ArrayList<Resource>();
550 
551         long groupId = webDavRequest.getGroupId();
552 
553         List<IGFolder> folders = IGFolderServiceUtil.getFolders(
554             groupId, parentFolderId);
555 
556         for (IGFolder folder : folders) {
557             Resource resource = toResource(webDavRequest, folder, true);
558 
559             resources.add(resource);
560         }
561 
562         return resources;
563     }
564 
565     protected List<Resource> getImages(
566             WebDAVRequest webDavRequest, long parentFolderId)
567         throws Exception {
568 
569         List<Resource> resources = new ArrayList<Resource>();
570 
571         List<IGImage> images = IGImageServiceUtil.getImages(parentFolderId);
572 
573         for (IGImage image : images) {
574             Resource resource = toResource(webDavRequest, image, true);
575 
576             resources.add(resource);
577         }
578 
579         return resources;
580     }
581 
582     protected long getFolderId(String[] pathArray) throws Exception {
583         return getFolderId(pathArray, false);
584     }
585 
586     protected long getFolderId(String[] pathArray, boolean parent)
587         throws Exception {
588 
589         long folderId = IGFolderImpl.DEFAULT_PARENT_FOLDER_ID;
590 
591         if (pathArray.length <= 2) {
592             return folderId;
593         }
594         else {
595             long groupId = WebDAVUtil.getGroupId(pathArray);
596 
597             int x = pathArray.length;
598 
599             if (parent) {
600                 x--;
601             }
602 
603             for (int i = 3; i < x; i++) {
604                 String name = pathArray[i];
605 
606                 IGFolder folder = IGFolderServiceUtil.getFolder(
607                     groupId, folderId, name);
608 
609                 if (groupId == folder.getGroupId()) {
610                     folderId = folder.getFolderId();
611                 }
612             }
613         }
614 
615         return folderId;
616     }
617 
618     protected long getParentFolderId(String[] pathArray) throws Exception {
619         return getFolderId(pathArray, true);
620     }
621 
622     protected Resource toResource(
623         WebDAVRequest webDavRequest, IGImage image, boolean appendPath) {
624 
625         String parentPath = getRootPath() + webDavRequest.getPath();
626         String name = StringPool.BLANK;
627 
628         if (appendPath) {
629             name = image.getNameWithExtension();
630         }
631 
632         return new IGImageResourceImpl(image, parentPath, name);
633     }
634 
635     protected Resource toResource(
636         WebDAVRequest webDavRequest, IGFolder folder, boolean appendPath) {
637 
638         String parentPath = getRootPath() + webDavRequest.getPath();
639         String name = StringPool.BLANK;
640 
641         if (appendPath) {
642             name = folder.getName();
643         }
644 
645         Resource resource = new BaseResourceImpl(
646             parentPath, name, folder.getName(), folder.getCreateDate(),
647             folder.getModifiedDate());
648 
649         resource.setModel(folder);
650         resource.setClassName(IGFolder.class.getName());
651         resource.setPrimaryKey(folder.getPrimaryKey());
652 
653         return resource;
654     }
655 
656     private static Log _log = LogFactoryUtil.getLog(IGWebDAVStorageImpl.class);
657 
658 }