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