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