1   /**
2    * Copyright (c) 2000-2009 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.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.ContentTypes;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.Tuple;
30  import com.liferay.portal.kernel.xml.Document;
31  import com.liferay.portal.kernel.xml.Element;
32  import com.liferay.portal.kernel.xml.Namespace;
33  import com.liferay.portal.kernel.xml.SAXReaderUtil;
34  import com.liferay.portal.model.WebDAVProps;
35  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
36  import com.liferay.portal.webdav.Resource;
37  import com.liferay.portal.webdav.WebDAVRequest;
38  import com.liferay.portal.webdav.WebDAVStorage;
39  import com.liferay.portal.webdav.WebDAVUtil;
40  import com.liferay.util.servlet.ServletResponseUtil;
41  import com.liferay.util.xml.DocUtil;
42  
43  import java.util.Arrays;
44  import java.util.HashSet;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Set;
48  
49  import javax.servlet.http.HttpServletResponse;
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         for (Tuple tuple : props) {
202             String name = (String)tuple.getObject(0);
203             Namespace namespace = (Namespace)tuple.getObject(1);
204 
205             String prefix = namespace.getPrefix();
206             String uri = namespace.getURI();
207 
208             if (customProps.contains(tuple)) {
209                 String text = webDavProps.getText(name, prefix, uri);
210 
211                 DocUtil.add(successProp, name, namespace, text);
212 
213                 hasSuccess = true;
214             }
215             else {
216                 DocUtil.add(failureProp, name, namespace);
217 
218                 hasFailure = true;
219             }
220         }
221 
222         // Clean up propstats
223 
224         if (hasSuccess) {
225             DocUtil.add(
226                 successStat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 200 OK");
227         }
228         else {
229             response.remove(successStat);
230         }
231 
232         if (!hasSuccess && hasFailure) {
233             DocUtil.add(
234                 failureStat, "status", WebDAVUtil.DAV_URI,
235                 "HTTP/1.1 404 Not Found");
236         }
237         else {
238             response.remove(failureStat);
239         }
240     }
241 
242     protected void addResponse(String href, Element multistatus)
243         throws Exception {
244 
245         Element response = DocUtil.add(
246             multistatus, "response", WebDAVUtil.DAV_URI);
247 
248         DocUtil.add(response, "href", WebDAVUtil.DAV_URI, href);
249 
250         Element propstat = DocUtil.add(
251             response, "propstat", WebDAVUtil.DAV_URI);
252 
253         DocUtil.add(
254             propstat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 404 Not Found");
255     }
256 
257     protected int writeResponseXML(
258             WebDAVRequest webDavRequest, Set<Tuple> props)
259         throws Exception {
260 
261         WebDAVStorage storage = webDavRequest.getWebDAVStorage();
262 
263         long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
264 
265         Document doc = SAXReaderUtil.createDocument();
266 
267         Element multistatus = SAXReaderUtil.createElement(
268             SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
269 
270         doc.setRootElement(multistatus);
271 
272         Resource resource = storage.getResource(webDavRequest);
273 
274         if (resource != null) {
275             addResponse(
276                 storage, webDavRequest, resource, props, multistatus, depth);
277 
278             String xml = doc.formattedString(StringPool.FOUR_SPACES);
279 
280             if (_log.isInfoEnabled()) {
281                 _log.info("Response XML\n" + xml);
282             }
283 
284             // Set the status prior to writing the XML
285 
286             HttpServletResponse response =
287                 webDavRequest.getHttpServletResponse();
288 
289             response.setContentType(ContentTypes.TEXT_XML_UTF8);
290             response.setStatus(WebDAVUtil.SC_MULTI_STATUS);
291 
292             try {
293                 ServletResponseUtil.write(response, xml);
294             }
295             catch (Exception e) {
296                 if (_log.isWarnEnabled()) {
297                     _log.warn(e);
298                 }
299             }
300 
301             return -1;
302         }
303         else {
304             if (_log.isDebugEnabled()) {
305                 _log.debug(
306                     "No resource found for " + storage.getRootPath() +
307                         webDavRequest.getPath());
308             }
309 
310             return HttpServletResponse.SC_NOT_FOUND;
311         }
312     }
313 
314     private static final String _ALLPROPS = "allprops";
315 
316     private static final String _CREATIONDATE = "creationdate";
317 
318     private static final String _DISPLAYNAME = "displayname";
319 
320     private static final String _GETLASTMODIFIED = "getlastmodified";
321 
322     private static final String _GETCONTENTTYPE = "getcontenttype";
323 
324     private static final String _GETCONTENTLENGTH = "getcontentlength";
325 
326     private static final String _RESOURCETYPE = "resourcetype";
327 
328     private static final Tuple _ALL_PROPS_PAIR =
329         new Tuple(_ALLPROPS, WebDAVUtil.DAV_URI);
330 
331     private static final Tuple _CREATIONDATE_PAIR =
332         new Tuple(_CREATIONDATE, WebDAVUtil.DAV_URI);
333 
334     private static final Tuple _DISPLAYNAME_PAIR =
335         new Tuple(_DISPLAYNAME, WebDAVUtil.DAV_URI);
336 
337     private static final Tuple _GETLASTMODIFIED_PAIR =
338         new Tuple(_GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
339 
340     private static final Tuple _GETCONTENTTYPE_PAIR =
341         new Tuple(_GETCONTENTTYPE, WebDAVUtil.DAV_URI);
342 
343     private static final Tuple _GETCONTENTLENGTH_PAIR =
344         new Tuple(_GETLASTMODIFIED, WebDAVUtil.DAV_URI);
345 
346     private static final Tuple _RESOURCETYPE_PAIR =
347         new Tuple(_RESOURCETYPE, WebDAVUtil.DAV_URI);
348 
349     private final List<Tuple> _ALL_COLLECTION_PROPS = Arrays.asList(
350         new Tuple[] {
351             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
352             _GETCONTENTTYPE_PAIR, _RESOURCETYPE_PAIR
353         });
354 
355     private final List<Tuple> _ALL_SIMPLE_PROPS = Arrays.asList(
356         new Tuple[] {
357             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
358             _GETCONTENTTYPE_PAIR, _GETCONTENTLENGTH_PAIR, _RESOURCETYPE_PAIR
359         });
360 
361     private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
362 
363 }