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