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