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.portal.webdav.methods;
24  
25  import com.liferay.portal.NoSuchGroupException;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.Tuple;
28  import com.liferay.portal.model.Group;
29  import com.liferay.portal.model.WebDAVProps;
30  import com.liferay.portal.service.GroupLocalServiceUtil;
31  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
32  import com.liferay.portal.webdav.BaseResourceImpl;
33  import com.liferay.portal.webdav.Resource;
34  import com.liferay.portal.webdav.WebDAVRequest;
35  import com.liferay.portal.webdav.WebDAVStorage;
36  import com.liferay.portal.webdav.WebDAVUtil;
37  import com.liferay.util.xml.DocUtil;
38  import com.liferay.util.xml.XMLFormatter;
39  
40  import java.util.Arrays;
41  import java.util.HashSet;
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.Set;
45  
46  import org.apache.commons.logging.Log;
47  import org.apache.commons.logging.LogFactory;
48  
49  import org.dom4j.Document;
50  import org.dom4j.DocumentFactory;
51  import org.dom4j.Element;
52  import org.dom4j.Namespace;
53  import org.dom4j.QName;
54  
55  /**
56   * <a href="BasePropMethodImpl.java.html"><b><i>View Source</i></b></a>
57   *
58   * @author Alexander Chow
59   *
60   */
61  public abstract class BasePropMethodImpl implements Method {
62  
63      protected void addResponse(
64              WebDAVStorage storage, WebDAVRequest webDavReq,
65              Resource resource, Set props, Element multistatus, long depth)
66          throws Exception {
67  
68          addResponse(webDavReq, resource, props, multistatus);
69  
70          if (resource.isCollection() && (depth != 0)) {
71              Iterator itr = storage.getResources(webDavReq).iterator();
72  
73              while (itr.hasNext()) {
74                  resource = (Resource)itr.next();
75  
76                  addResponse(webDavReq, resource, props, multistatus);
77              }
78          }
79      }
80  
81      protected void addResponse(
82              WebDAVRequest webDavReq, Resource resource, Set props,
83              Element multistatus)
84          throws Exception {
85  
86          // Make a deep copy of the props
87  
88          props = new HashSet(props);
89  
90          // Start building multistatus response
91  
92          Element response = DocUtil.add(
93              multistatus, "response", WebDAVUtil.DAV_URI);
94  
95          DocUtil.add(response, "href", WebDAVUtil.DAV_URI, resource.getHREF());
96  
97          // Build success and failure propstat elements
98  
99          Element successStat = DocUtil.add(
100             response, "propstat", WebDAVUtil.DAV_URI);
101         Element successProp = DocUtil.add(
102             successStat, "prop", WebDAVUtil.DAV_URI);
103         Element failureStat = DocUtil.add(
104             response, "propstat", WebDAVUtil.DAV_URI);
105         Element failureProp = DocUtil.add(
106             failureStat, "prop", WebDAVUtil.DAV_URI);
107 
108         boolean hasSuccess = false;
109         boolean hasFailure = false;
110 
111         // Check DAV properties
112 
113         if (props.contains(_ALL_PROPS_PAIR)) {
114             props.remove(_ALL_PROPS_PAIR);
115 
116             if (resource.isCollection()) {
117                 props.addAll(_ALL_COLLECTION_PROPS);
118             }
119             else {
120                 props.addAll(_ALL_SIMPLE_PROPS);
121             }
122         }
123 
124         if (props.contains(_CREATIONDATE_PAIR)) {
125             props.remove(_CREATIONDATE_PAIR);
126 
127             DocUtil.add(
128                 successProp, _CREATIONDATE, WebDAVUtil.DAV_URI,
129                 resource.getCreateDate());
130 
131             hasSuccess = true;
132         }
133 
134         if (props.contains(_DISPLAYNAME_PAIR)) {
135             props.remove(_DISPLAYNAME_PAIR);
136 
137             DocUtil.add(
138                 successProp, _DISPLAYNAME, WebDAVUtil.DAV_URI,
139                 resource.getDisplayName());
140 
141             hasSuccess = true;
142         }
143 
144         if (props.contains(_GETLASTMODIFIED_PAIR)) {
145             props.remove(_GETLASTMODIFIED_PAIR);
146 
147             DocUtil.add(
148                 successProp, _GETLASTMODIFIED, WebDAVUtil.DAV_URI,
149                 resource.getModifiedDate());
150 
151             hasSuccess = true;
152         }
153 
154         if (props.contains(_GETCONTENTTYPE_PAIR)) {
155             props.remove(_GETCONTENTTYPE_PAIR);
156 
157             DocUtil.add(
158                 successProp, _GETCONTENTTYPE, WebDAVUtil.DAV_URI,
159                 resource.getContentType());
160 
161             hasSuccess = true;
162         }
163 
164         if (props.contains(_GETCONTENTLENGTH_PAIR)) {
165             props.remove(_GETCONTENTLENGTH_PAIR);
166 
167             if (!resource.isCollection()) {
168                 DocUtil.add(
169                     successProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI,
170                     resource.getSize());
171 
172                 hasSuccess = true;
173             }
174             else {
175                 DocUtil.add(
176                     failureProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
177 
178                 hasFailure = true;
179             }
180         }
181 
182         if (props.contains(_RESOURCETYPE_PAIR)) {
183             props.remove(_RESOURCETYPE_PAIR);
184 
185             Element resourceType =
186                 DocUtil.add(successProp, _RESOURCETYPE, WebDAVUtil.DAV_URI);
187 
188             if (resource.isCollection()) {
189                 DocUtil.add(resourceType, "collection", WebDAVUtil.DAV_URI);
190             }
191 
192             hasSuccess = true;
193         }
194 
195         // Check remaining properties against custom properties
196 
197         WebDAVProps webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
198             webDavReq.getCompanyId(), resource.getClassName(),
199             resource.getPrimaryKey());
200 
201         Set customProps = webDavProps.getPropsSet();
202 
203         Iterator itr = props.iterator();
204 
205         while (itr.hasNext()) {
206             Tuple tuple = (Tuple)itr.next();
207 
208             String name = (String)tuple.getObject(0);
209             Namespace namespace = (Namespace)tuple.getObject(1);
210 
211             String prefix = namespace.getPrefix();
212             String uri = namespace.getURI();
213 
214             if (customProps.contains(tuple)) {
215                 String text = webDavProps.getText(name, prefix, uri);
216 
217                 DocUtil.add(successProp, name, namespace, text);
218 
219                 hasSuccess = true;
220             }
221             else {
222                 DocUtil.add(failureProp, name, namespace);
223 
224                 hasFailure = true;
225             }
226         }
227 
228         // Clean up propstats
229 
230         if (hasSuccess) {
231             DocUtil.add(
232                 successStat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 200 OK");
233         }
234         else {
235             response.remove(successStat);
236         }
237 
238         if (hasFailure) {
239             DocUtil.add(
240                 failureStat, "status", WebDAVUtil.DAV_URI,
241                 "HTTP/1.1 404 Not Found");
242         }
243         else {
244             response.remove(failureStat);
245         }
246     }
247 
248     protected void addResponse(String href, Element multistatus)
249         throws Exception {
250 
251         Element response = DocUtil.add(
252             multistatus, "response", WebDAVUtil.DAV_URI);
253 
254         DocUtil.add(response, "href", WebDAVUtil.DAV_URI, href);
255 
256         Element propstat = DocUtil.add(
257             response, "propstat", WebDAVUtil.DAV_URI);
258 
259         DocUtil.add(
260             propstat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 404 Not Found");
261     }
262 
263     protected String getResponseXML(WebDAVRequest webDavReq, Set props)
264         throws Exception {
265 
266         WebDAVStorage storage = webDavReq.getWebDAVStorage();
267 
268         long companyId = webDavReq.getCompanyId();
269         long groupId = webDavReq.getGroupId();
270         long depth = WebDAVUtil.getDepth(webDavReq.getHttpServletRequest());
271 
272         DocumentFactory docFactory = DocumentFactory.getInstance();
273 
274         Document doc = docFactory.createDocument();
275 
276         Element multistatus = docFactory.createElement(
277             new QName("multistatus", WebDAVUtil.DAV_URI));
278 
279         doc.setRootElement(multistatus);
280 
281         if (companyId <= 0) {
282             return getResponseXML(doc);
283         }
284 
285         if (groupId == 0) {
286             addResponse(
287                 webDavReq,
288                 new BaseResourceImpl(
289                     storage.getRootPath(), companyId, companyId),
290                 props, multistatus);
291 
292             if (props.size() > 0) {
293                 Iterator itr = storage.getCommunities(webDavReq).iterator();
294 
295                 while (itr.hasNext()) {
296                     Resource resource = (Resource)itr.next();
297 
298                     addResponse(webDavReq, resource, props, multistatus);
299                 }
300             }
301 
302             return getResponseXML(doc);
303         }
304 
305         Resource resource = storage.getResource(webDavReq);
306 
307         if ((resource == null) && !webDavReq.isGroupPath()) {
308             String href = storage.getRootPath() + webDavReq.getPath();
309 
310             if (_log.isWarnEnabled()) {
311                 _log.warn("No resource found for " + webDavReq.getPath());
312             }
313 
314             addResponse(href, multistatus);
315 
316             return getResponseXML(doc);
317         }
318 
319         try {
320             if (resource != null) {
321                 addResponse(
322                     storage, webDavReq, resource, props, multistatus, depth);
323             }
324             else if (webDavReq.isGroupPath()) {
325                 Group group = GroupLocalServiceUtil.getGroup(groupId);
326 
327                 resource = new BaseResourceImpl(
328                     storage.getRootPath() + StringPool.SLASH + companyId,
329                     groupId, group.getName());
330 
331                 addResponse(
332                     storage, webDavReq, resource, props, multistatus, depth);
333             }
334         }
335         catch (NoSuchGroupException nsge) {
336             String href = storage.getRootPath() + webDavReq.getPath();
337 
338             if (_log.isWarnEnabled()) {
339                 _log.warn("No group found for " + href);
340             }
341 
342             addResponse(href, multistatus);
343         }
344 
345         return getResponseXML(doc);
346     }
347 
348     protected String getResponseXML(Document doc) throws Exception {
349         String xml = XMLFormatter.toString(doc, StringPool.FOUR_SPACES);
350 
351         if (_log.isDebugEnabled()) {
352             _log.debug("Response XML\n" + xml);
353         }
354 
355         return xml;
356     }
357 
358     private static final String _ALLPROPS = "allprops";
359 
360     private static final String _CREATIONDATE = "creationdate";
361 
362     private static final String _DISPLAYNAME = "displayname";
363 
364     private static final String _GETLASTMODIFIED = "getlastmodified";
365 
366     private static final String _GETCONTENTTYPE = "getcontenttype";
367 
368     private static final String _GETCONTENTLENGTH = "getcontentlength";
369 
370     private static final String _RESOURCETYPE = "resourcetype";
371 
372     private static final Tuple _ALL_PROPS_PAIR =
373         new Tuple(_ALLPROPS, WebDAVUtil.DAV_URI);
374 
375     private static final Tuple _CREATIONDATE_PAIR =
376         new Tuple(_CREATIONDATE, WebDAVUtil.DAV_URI);
377 
378     private static final Tuple _DISPLAYNAME_PAIR =
379         new Tuple(_DISPLAYNAME, WebDAVUtil.DAV_URI);
380 
381     private static final Tuple _GETLASTMODIFIED_PAIR =
382         new Tuple(_GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
383 
384     private static final Tuple _GETCONTENTTYPE_PAIR =
385         new Tuple(_GETCONTENTTYPE, WebDAVUtil.DAV_URI);
386 
387     private static final Tuple _GETCONTENTLENGTH_PAIR =
388         new Tuple(_GETLASTMODIFIED, WebDAVUtil.DAV_URI);
389 
390     private static final Tuple _RESOURCETYPE_PAIR =
391         new Tuple(_RESOURCETYPE, WebDAVUtil.DAV_URI);
392 
393     private final List _ALL_COLLECTION_PROPS = Arrays.asList(
394         new Object[] {
395             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
396             _GETCONTENTTYPE_PAIR, _RESOURCETYPE_PAIR
397         });
398 
399     private final List _ALL_SIMPLE_PROPS = Arrays.asList(
400         new Object[] {
401             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
402             _GETCONTENTTYPE_PAIR, _GETCONTENTLENGTH_PAIR, _RESOURCETYPE_PAIR
403         });
404 
405     private static Log _log = LogFactory.getLog(BasePropMethodImpl.class);
406 
407 }