1   /**
2    * Copyright (c) 2000-2008 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.documentlibrary.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.util.FileUtil;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.security.auth.PrincipalException;
33  import com.liferay.portal.webdav.BaseResourceImpl;
34  import com.liferay.portal.webdav.BaseWebDAVStorageImpl;
35  import com.liferay.portal.webdav.Resource;
36  import com.liferay.portal.webdav.Status;
37  import com.liferay.portal.webdav.WebDAVException;
38  import com.liferay.portal.webdav.WebDAVRequest;
39  import com.liferay.portal.webdav.WebDAVUtil;
40  import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
41  import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
42  import com.liferay.portlet.documentlibrary.NoSuchFolderException;
43  import com.liferay.portlet.documentlibrary.model.DLFileEntry;
44  import com.liferay.portlet.documentlibrary.model.DLFolder;
45  import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
46  import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
47  import com.liferay.portlet.documentlibrary.service.DLFileEntryServiceUtil;
48  import com.liferay.portlet.documentlibrary.service.DLFolderServiceUtil;
49  import com.liferay.portlet.tags.service.TagsEntryLocalServiceUtil;
50  
51  import java.io.File;
52  import java.io.InputStream;
53  
54  import java.rmi.RemoteException;
55  
56  import java.util.ArrayList;
57  import java.util.List;
58  
59  import javax.servlet.http.HttpServletRequest;
60  import javax.servlet.http.HttpServletResponse;
61  
62  import org.apache.commons.logging.Log;
63  import org.apache.commons.logging.LogFactory;
64  
65  /**
66   * <a href="DLWebDAVStorageImpl.java.html"><b><i>View Source</i></b></a>
67   *
68   * @author Brian Wing Shun Chan
69   * @author Alexander Chow
70   *
71   */
72  public class DLWebDAVStorageImpl extends BaseWebDAVStorageImpl {
73  
74      public int copyCollectionResource(
75              WebDAVRequest webDavRequest, Resource resource, String destination,
76              boolean overwrite, long depth)
77          throws WebDAVException {
78  
79          try {
80              String[] destinationArray = WebDAVUtil.getPathArray(
81                  destination, true);
82  
83              long parentFolderId = DLFolderImpl.DEFAULT_PARENT_FOLDER_ID;
84  
85              try {
86                  parentFolderId = getParentFolderId(destinationArray);
87              }
88              catch (NoSuchFolderException nsfe) {
89                  return HttpServletResponse.SC_CONFLICT;
90              }
91  
92              DLFolder folder = (DLFolder)resource.getModel();
93  
94              long groupId = WebDAVUtil.getGroupId(destination);
95              long plid = getPlid(groupId);
96              String name = WebDAVUtil.getResourceName(destinationArray);
97              String description = folder.getDescription();
98              boolean addCommunityPermissions = true;
99              boolean addGuestPermissions = true;
100 
101             int status = HttpServletResponse.SC_CREATED;
102 
103             if (overwrite) {
104                 if (deleteResource(groupId, parentFolderId, name)) {
105                     status = HttpServletResponse.SC_NO_CONTENT;
106                 }
107             }
108 
109             if (depth == 0) {
110                 DLFolderServiceUtil.addFolder(
111                     plid, parentFolderId, name, description,
112                     addCommunityPermissions, addGuestPermissions);
113             }
114             else {
115                 DLFolderServiceUtil.copyFolder(
116                     plid, folder.getFolderId(), parentFolderId, name,
117                     description, addCommunityPermissions, addGuestPermissions);
118             }
119 
120             return status;
121         }
122         catch (DuplicateFolderNameException dfne) {
123             return HttpServletResponse.SC_PRECONDITION_FAILED;
124         }
125         catch (PrincipalException pe) {
126             return HttpServletResponse.SC_FORBIDDEN;
127         }
128         catch (Exception e) {
129             throw new WebDAVException(e);
130         }
131     }
132 
133     public int copySimpleResource(
134             WebDAVRequest webDavRequest, Resource resource, String destination,
135             boolean overwrite)
136         throws WebDAVException {
137 
138         File file = null;
139 
140         try {
141             String[] destinationArray = WebDAVUtil.getPathArray(
142                 destination, true);
143 
144             long parentFolderId = DLFolderImpl.DEFAULT_PARENT_FOLDER_ID;
145 
146             try {
147                 parentFolderId = getParentFolderId(destinationArray);
148             }
149             catch (NoSuchFolderException nsfe) {
150                 return HttpServletResponse.SC_CONFLICT;
151             }
152 
153             DLFileEntry fileEntry = (DLFileEntry)resource.getModel();
154 
155             long groupId = WebDAVUtil.getGroupId(destination);
156             long userId = webDavRequest.getUserId();
157             String name = WebDAVUtil.getResourceName(destinationArray);
158             String title = WebDAVUtil.getResourceName(destinationArray);
159             String description = fileEntry.getDescription();
160             String[] tagsEntries = null;
161             String extraSettings = fileEntry.getExtraSettings();
162 
163             file = FileUtil.createTempFile(
164                 FileUtil.getExtension(fileEntry.getName()));
165 
166             InputStream is = DLFileEntryLocalServiceUtil.getFileAsStream(
167                 fileEntry.getCompanyId(), userId, fileEntry.getFolderId(),
168                 fileEntry.getName());
169 
170             FileUtil.write(file, is);
171 
172             boolean addCommunityPermissions = true;
173             boolean addGuestPermissions = true;
174 
175             int status = HttpServletResponse.SC_CREATED;
176 
177             if (overwrite) {
178                 if (deleteResource(groupId, parentFolderId, title)) {
179                     status = HttpServletResponse.SC_NO_CONTENT;
180                 }
181             }
182 
183             DLFileEntryServiceUtil.addFileEntry(
184                 parentFolderId, name, title, description, tagsEntries,
185                 extraSettings, file, addCommunityPermissions,
186                 addGuestPermissions);
187 
188             return status;
189         }
190         catch (DuplicateFolderNameException dfne) {
191             return HttpServletResponse.SC_PRECONDITION_FAILED;
192         }
193         catch (DuplicateFileException dfe) {
194             return HttpServletResponse.SC_PRECONDITION_FAILED;
195         }
196         catch (PrincipalException pe) {
197             return HttpServletResponse.SC_FORBIDDEN;
198         }
199         catch (Exception e) {
200             throw new WebDAVException(e);
201         }
202         finally {
203             if (file != null) {
204                 file.delete();
205             }
206         }
207     }
208 
209     public int deleteResource(WebDAVRequest webDavRequest)
210         throws WebDAVException {
211 
212         try {
213             Resource resource = getResource(webDavRequest);
214 
215             if (resource == null) {
216                 return HttpServletResponse.SC_NOT_FOUND;
217             }
218 
219             Object model = resource.getModel();
220 
221             if (model instanceof DLFolder) {
222                 DLFolder folder = (DLFolder)model;
223 
224                 DLFolderServiceUtil.deleteFolder(folder.getFolderId());
225             }
226             else {
227                 DLFileEntry fileEntry = (DLFileEntry)model;
228 
229                 DLFileEntryServiceUtil.deleteFileEntry(
230                     fileEntry.getFolderId(), fileEntry.getName());
231             }
232 
233             return HttpServletResponse.SC_NO_CONTENT;
234         }
235         catch (PrincipalException pe) {
236             return HttpServletResponse.SC_FORBIDDEN;
237         }
238         catch (Exception e) {
239             throw new WebDAVException(e);
240         }
241     }
242 
243     public Resource getResource(WebDAVRequest webDavRequest)
244         throws WebDAVException {
245 
246         try {
247             String[] pathArray = webDavRequest.getPathArray();
248 
249             long parentFolderId = getParentFolderId(pathArray);
250             String name = WebDAVUtil.getResourceName(pathArray);
251 
252             if (Validator.isNull(name)) {
253                 String path = getRootPath() + webDavRequest.getPath();
254 
255                 return new BaseResourceImpl(path, StringPool.BLANK, getToken());
256             }
257 
258             try {
259                 DLFolder folder = DLFolderServiceUtil.getFolder(
260                     webDavRequest.getGroupId(), parentFolderId, name);
261 
262                 if ((folder.getParentFolderId() != parentFolderId) ||
263                     (webDavRequest.getGroupId() != folder.getGroupId())) {
264 
265                     throw new NoSuchFolderException();
266                 }
267 
268                 return toResource(webDavRequest, folder, false);
269             }
270             catch (NoSuchFolderException nsfe) {
271                 try {
272                     String titleWithExtension = name;
273 
274                     DLFileEntry fileEntry =
275                         DLFileEntryServiceUtil.getFileEntryByTitle(
276                             parentFolderId, titleWithExtension);
277 
278                     return toResource(webDavRequest, fileEntry, false);
279                 }
280                 catch (NoSuchFileEntryException nsfee) {
281                     return null;
282                 }
283             }
284         }
285         catch (Exception e) {
286             throw new WebDAVException(e);
287         }
288     }
289 
290     public List<Resource> getResources(WebDAVRequest webDavRequest)
291         throws WebDAVException {
292 
293         try {
294             long folderId = getFolderId(webDavRequest.getPathArray());
295 
296             List<Resource> folders = getFolders(webDavRequest, folderId);
297             List<Resource> fileEntries = getFileEntries(
298                 webDavRequest, folderId);
299 
300             List<Resource> resources = new ArrayList<Resource>(
301                 folders.size() + fileEntries.size());
302 
303             resources.addAll(folders);
304             resources.addAll(fileEntries);
305 
306             return resources;
307         }
308         catch (Exception e) {
309             throw new WebDAVException(e);
310         }
311     }
312 
313     public Status makeCollection(WebDAVRequest webDavRequest)
314         throws WebDAVException {
315 
316         try {
317             HttpServletRequest request = webDavRequest.getHttpServletRequest();
318 
319             if (request.getContentLength() > 0) {
320                 return new Status(
321                     HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
322             }
323 
324             String[] pathArray = webDavRequest.getPathArray();
325 
326             long plid = getPlid(webDavRequest.getGroupId());
327             long parentFolderId = getParentFolderId(pathArray);
328             String name = WebDAVUtil.getResourceName(pathArray);
329             String description = StringPool.BLANK;
330             boolean addCommunityPermissions = true;
331             boolean addGuestPermissions = true;
332 
333             DLFolderServiceUtil.addFolder(
334                 plid, parentFolderId, name, description,
335                 addCommunityPermissions, addGuestPermissions);
336 
337             String location = StringUtil.merge(pathArray, StringPool.SLASH);
338 
339             return new Status(location, HttpServletResponse.SC_CREATED);
340         }
341         catch (DuplicateFolderNameException dfne) {
342             return new Status(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
343         }
344         catch (NoSuchFolderException nsfe) {
345             return new Status(HttpServletResponse.SC_CONFLICT);
346         }
347         catch (PrincipalException pe) {
348             return new Status(HttpServletResponse.SC_FORBIDDEN);
349         }
350         catch (Exception e) {
351             throw new WebDAVException(e);
352         }
353     }
354 
355     public int moveCollectionResource(
356             WebDAVRequest webDavRequest, Resource resource, String destination,
357             boolean overwrite)
358         throws WebDAVException {
359 
360         try {
361             String[] destinationArray = WebDAVUtil.getPathArray(
362                 destination, true);
363 
364             DLFolder folder = (DLFolder)resource.getModel();
365 
366             long groupId = WebDAVUtil.getGroupId(destinationArray);
367             long folderId = folder.getFolderId();
368             long parentFolderId = getParentFolderId(destinationArray);
369             String name = WebDAVUtil.getResourceName(destinationArray);
370             String description = folder.getDescription();
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             DLFolderServiceUtil.updateFolder(
381                 folderId, parentFolderId, name, description);
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             DLFileEntry fileEntry = (DLFileEntry)resource.getModel();
406 
407             long groupId = WebDAVUtil.getGroupId(destinationArray);
408             long parentFolderId = getParentFolderId(destinationArray);
409             String name = fileEntry.getName();
410             String sourceFileName = null;
411             String title = WebDAVUtil.getResourceName(destinationArray);
412             String description = fileEntry.getDescription();
413             String[] tagsEntries = null;
414             String extraSettings = fileEntry.getExtraSettings();
415             byte[] bytes = null;
416 
417             int status = HttpServletResponse.SC_CREATED;
418 
419             if (overwrite) {
420                 if (deleteResource(groupId, parentFolderId, title)) {
421                     status = HttpServletResponse.SC_NO_CONTENT;
422                 }
423             }
424 
425             DLFileEntryServiceUtil.updateFileEntry(
426                 fileEntry.getFolderId(), parentFolderId, name, sourceFileName,
427                 title, description, tagsEntries, extraSettings, bytes);
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 parentFolderId = getParentFolderId(pathArray);
454             String name = WebDAVUtil.getResourceName(pathArray);
455             String title = name;
456             String description = StringPool.BLANK;
457             String[] tagsEntries = null;
458             String extraSettings = StringPool.BLANK;
459             boolean addCommunityPermissions = true;
460             boolean addGuestPermissions = true;
461 
462             try {
463                 DLFileEntry entry = DLFileEntryServiceUtil.getFileEntryByTitle(
464                     parentFolderId, name);
465 
466                 name = entry.getName();
467                 description = entry.getDescription();
468                 tagsEntries = TagsEntryLocalServiceUtil.getEntryNames(
469                     DLFileEntry.class.getName(), entry.getFileEntryId());
470                 extraSettings = entry.getExtraSettings();
471 
472                 DLFileEntryServiceUtil.updateFileEntry(
473                     parentFolderId, parentFolderId, name, title, title,
474                     description, tagsEntries, extraSettings,
475                     FileUtil.getBytes(request.getInputStream()));
476             }
477             catch (NoSuchFileEntryException nsfee) {
478                 file = FileUtil.createTempFile(FileUtil.getExtension(name));
479 
480                 FileUtil.write(file, request.getInputStream());
481 
482                 DLFileEntryServiceUtil.addFileEntry(
483                     parentFolderId, name, title, description, tagsEntries,
484                     extraSettings, file, addCommunityPermissions,
485                     addGuestPermissions);
486             }
487 
488             return HttpServletResponse.SC_CREATED;
489         }
490         catch (PrincipalException pe) {
491             return HttpServletResponse.SC_FORBIDDEN;
492         }
493         catch (PortalException pe) {
494             if (_log.isWarnEnabled()) {
495                 _log.warn(pe, pe);
496             }
497 
498             return HttpServletResponse.SC_CONFLICT;
499         }
500         catch (Exception e) {
501             throw new WebDAVException(e);
502         }
503         finally {
504             if (file != null) {
505                 file.delete();
506             }
507         }
508     }
509 
510     protected boolean deleteResource(
511             long groupId, long parentFolderId, String name)
512         throws PortalException, SystemException, RemoteException {
513 
514         try {
515             DLFolder folder = DLFolderServiceUtil.getFolder(
516                 groupId, parentFolderId, name);
517 
518             DLFolderServiceUtil.deleteFolder(folder.getFolderId());
519 
520             return true;
521         }
522         catch (NoSuchFolderException nsfe) {
523             try {
524                 DLFileEntryServiceUtil.deleteFileEntryByTitle(
525                     parentFolderId, name);
526 
527                 return true;
528             }
529             catch (NoSuchFileEntryException nsfee) {
530             }
531         }
532 
533         return false;
534     }
535 
536     protected List<Resource> getFileEntries(
537             WebDAVRequest webDavRequest, long parentFolderId)
538         throws Exception {
539 
540         List<Resource> resources = new ArrayList<Resource>();
541 
542         List<DLFileEntry> fileEntries = DLFileEntryServiceUtil.getFileEntries(
543             parentFolderId);
544 
545         for (DLFileEntry fileEntry : fileEntries) {
546             Resource resource = toResource(webDavRequest, fileEntry, true);
547 
548             resources.add(resource);
549         }
550 
551         return resources;
552     }
553 
554     protected long getFolderId(String[] pathArray) throws Exception {
555         return getFolderId(pathArray, false);
556     }
557 
558     protected long getFolderId(String[] pathArray, boolean parent)
559         throws Exception {
560 
561         long folderId = DLFolderImpl.DEFAULT_PARENT_FOLDER_ID;
562 
563         if (pathArray.length <= 2) {
564             return folderId;
565         }
566         else {
567             long groupId = WebDAVUtil.getGroupId(pathArray);
568 
569             int x = pathArray.length;
570 
571             if (parent) {
572                 x--;
573             }
574 
575             for (int i = 3; i < x; i++) {
576                 String name = pathArray[i];
577 
578                 DLFolder folder = DLFolderServiceUtil.getFolder(
579                     groupId, folderId, name);
580 
581                 if (groupId == folder.getGroupId()) {
582                     folderId = folder.getFolderId();
583                 }
584             }
585         }
586 
587         return folderId;
588     }
589 
590     protected List<Resource> getFolders(
591             WebDAVRequest webDavRequest, long parentFolderId)
592         throws Exception {
593 
594         List<Resource> resources = new ArrayList<Resource>();
595 
596         long groupId = webDavRequest.getGroupId();
597 
598         List<DLFolder> folders = DLFolderServiceUtil.getFolders(
599             groupId, parentFolderId);
600 
601         for (DLFolder folder : folders) {
602             Resource resource = toResource(webDavRequest, folder, true);
603 
604             resources.add(resource);
605         }
606 
607         return resources;
608     }
609 
610     protected long getParentFolderId(String[] pathArray) throws Exception {
611         return getFolderId(pathArray, true);
612     }
613 
614     protected Resource toResource(
615         WebDAVRequest webDavRequest, DLFileEntry fileEntry,
616         boolean appendPath) {
617 
618         String parentPath = getRootPath() + webDavRequest.getPath();
619         String name = StringPool.BLANK;
620 
621         if (appendPath) {
622             name = fileEntry.getTitleWithExtension();
623         }
624 
625         return new DLFileEntryResourceImpl(
626             webDavRequest, fileEntry, parentPath, name);
627     }
628 
629     protected Resource toResource(
630         WebDAVRequest webDavRequest, DLFolder folder, boolean appendPath) {
631 
632         String parentPath = getRootPath() + webDavRequest.getPath();
633         String name = StringPool.BLANK;
634 
635         if (appendPath) {
636             name = folder.getName();
637         }
638 
639         Resource resource = new BaseResourceImpl(
640             parentPath, name, folder.getName(), folder.getCreateDate(),
641             folder.getModifiedDate());
642 
643         resource.setModel(folder);
644         resource.setClassName(DLFolder.class.getName());
645         resource.setPrimaryKey(folder.getPrimaryKey());
646 
647         return resource;
648     }
649 
650     private static Log _log = LogFactory.getLog(DLWebDAVStorageImpl.class);
651 
652 }