1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.webdav.methods;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.util.ContentTypes;
20  import com.liferay.portal.kernel.util.StringPool;
21  import com.liferay.portal.kernel.util.Tuple;
22  import com.liferay.portal.kernel.xml.Document;
23  import com.liferay.portal.kernel.xml.Element;
24  import com.liferay.portal.kernel.xml.Namespace;
25  import com.liferay.portal.kernel.xml.SAXReaderUtil;
26  import com.liferay.portal.model.WebDAVProps;
27  import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
28  import com.liferay.portal.webdav.Resource;
29  import com.liferay.portal.webdav.WebDAVRequest;
30  import com.liferay.portal.webdav.WebDAVStorage;
31  import com.liferay.portal.webdav.WebDAVUtil;
32  import com.liferay.util.servlet.ServletResponseUtil;
33  import com.liferay.util.xml.DocUtil;
34  
35  import java.util.Arrays;
36  import java.util.HashSet;
37  import java.util.Iterator;
38  import java.util.List;
39  import java.util.Set;
40  
41  import javax.servlet.http.HttpServletResponse;
42  
43  /**
44   * <a href="BasePropMethodImpl.java.html"><b><i>View Source</i></b></a>
45   *
46   * @author Alexander Chow
47   */
48  public abstract class BasePropMethodImpl implements Method {
49  
50      protected void addResponse(
51              WebDAVStorage storage, WebDAVRequest webDavRequest,
52              Resource resource, Set<Tuple> props, Element multistatus,
53              long depth)
54          throws Exception {
55  
56          addResponse(webDavRequest, resource, props, multistatus);
57  
58          if (resource.isCollection() && (depth != 0)) {
59              Iterator<Resource> itr = storage.getResources(
60                  webDavRequest).iterator();
61  
62              while (itr.hasNext()) {
63                  resource = itr.next();
64  
65                  addResponse(webDavRequest, resource, props, multistatus);
66              }
67          }
68      }
69  
70      protected void addResponse(
71              WebDAVRequest webDavRequest, Resource resource, Set<Tuple> props,
72              Element multistatus)
73          throws Exception {
74  
75          // Make a deep copy of the props
76  
77          props = new HashSet<Tuple>(props);
78  
79          // Start building multistatus response
80  
81          Element response = DocUtil.add(
82              multistatus, "response", WebDAVUtil.DAV_URI);
83  
84          DocUtil.add(response, "href", WebDAVUtil.DAV_URI, resource.getHREF());
85  
86          // Build success and failure propstat elements
87  
88          Element successStat = DocUtil.add(
89              response, "propstat", WebDAVUtil.DAV_URI);
90          Element successProp = DocUtil.add(
91              successStat, "prop", WebDAVUtil.DAV_URI);
92          Element failureStat = DocUtil.add(
93              response, "propstat", WebDAVUtil.DAV_URI);
94          Element failureProp = DocUtil.add(
95              failureStat, "prop", WebDAVUtil.DAV_URI);
96  
97          boolean hasSuccess = false;
98          boolean hasFailure = false;
99  
100         // Check DAV properties
101 
102         if (props.contains(_ALL_PROPS_PAIR)) {
103             props.remove(_ALL_PROPS_PAIR);
104 
105             if (resource.isCollection()) {
106                 props.addAll(_ALL_COLLECTION_PROPS);
107             }
108             else {
109                 props.addAll(_ALL_SIMPLE_PROPS);
110             }
111         }
112 
113         if (props.contains(_CREATIONDATE_PAIR)) {
114             props.remove(_CREATIONDATE_PAIR);
115 
116             DocUtil.add(
117                 successProp, _CREATIONDATE, WebDAVUtil.DAV_URI,
118                 resource.getCreateDate());
119 
120             hasSuccess = true;
121         }
122 
123         if (props.contains(_DISPLAYNAME_PAIR)) {
124             props.remove(_DISPLAYNAME_PAIR);
125 
126             DocUtil.add(
127                 successProp, _DISPLAYNAME, WebDAVUtil.DAV_URI,
128                 resource.getDisplayName());
129 
130             hasSuccess = true;
131         }
132 
133         if (props.contains(_GETLASTMODIFIED_PAIR)) {
134             props.remove(_GETLASTMODIFIED_PAIR);
135 
136             DocUtil.add(
137                 successProp, _GETLASTMODIFIED, WebDAVUtil.DAV_URI,
138                 resource.getModifiedDate());
139 
140             hasSuccess = true;
141         }
142 
143         if (props.contains(_GETCONTENTTYPE_PAIR)) {
144             props.remove(_GETCONTENTTYPE_PAIR);
145 
146             DocUtil.add(
147                 successProp, _GETCONTENTTYPE, WebDAVUtil.DAV_URI,
148                 resource.getContentType());
149 
150             hasSuccess = true;
151         }
152 
153         if (props.contains(_GETCONTENTLENGTH_PAIR)) {
154             props.remove(_GETCONTENTLENGTH_PAIR);
155 
156             if (!resource.isCollection()) {
157                 DocUtil.add(
158                     successProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI,
159                     resource.getSize());
160 
161                 hasSuccess = true;
162             }
163             else {
164                 DocUtil.add(
165                     failureProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
166 
167                 hasFailure = true;
168             }
169         }
170 
171         if (props.contains(_RESOURCETYPE_PAIR)) {
172             props.remove(_RESOURCETYPE_PAIR);
173 
174             Element resourceType =
175                 DocUtil.add(successProp, _RESOURCETYPE, WebDAVUtil.DAV_URI);
176 
177             if (resource.isCollection()) {
178                 DocUtil.add(resourceType, "collection", WebDAVUtil.DAV_URI);
179             }
180 
181             hasSuccess = true;
182         }
183 
184         // Check remaining properties against custom properties
185 
186         WebDAVProps webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
187             webDavRequest.getCompanyId(), resource.getClassName(),
188             resource.getPrimaryKey());
189 
190         Set<Tuple> customProps = webDavProps.getPropsSet();
191 
192         for (Tuple tuple : props) {
193             String name = (String)tuple.getObject(0);
194             Namespace namespace = (Namespace)tuple.getObject(1);
195 
196             String prefix = namespace.getPrefix();
197             String uri = namespace.getURI();
198 
199             if (customProps.contains(tuple)) {
200                 String text = webDavProps.getText(name, prefix, uri);
201 
202                 DocUtil.add(successProp, name, namespace, text);
203 
204                 hasSuccess = true;
205             }
206             else {
207                 DocUtil.add(failureProp, name, namespace);
208 
209                 hasFailure = true;
210             }
211         }
212 
213         // Clean up propstats
214 
215         if (hasSuccess) {
216             DocUtil.add(
217                 successStat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 200 OK");
218         }
219         else {
220             response.remove(successStat);
221         }
222 
223         if (!hasSuccess && hasFailure) {
224             DocUtil.add(
225                 failureStat, "status", WebDAVUtil.DAV_URI,
226                 "HTTP/1.1 404 Not Found");
227         }
228         else {
229             response.remove(failureStat);
230         }
231     }
232 
233     protected void addResponse(String href, Element multistatus)
234         throws Exception {
235 
236         Element response = DocUtil.add(
237             multistatus, "response", WebDAVUtil.DAV_URI);
238 
239         DocUtil.add(response, "href", WebDAVUtil.DAV_URI, href);
240 
241         Element propstat = DocUtil.add(
242             response, "propstat", WebDAVUtil.DAV_URI);
243 
244         DocUtil.add(
245             propstat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 404 Not Found");
246     }
247 
248     protected int writeResponseXML(
249             WebDAVRequest webDavRequest, Set<Tuple> props)
250         throws Exception {
251 
252         WebDAVStorage storage = webDavRequest.getWebDAVStorage();
253 
254         long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
255 
256         Document doc = SAXReaderUtil.createDocument();
257 
258         Element multistatus = SAXReaderUtil.createElement(
259             SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
260 
261         doc.setRootElement(multistatus);
262 
263         Resource resource = storage.getResource(webDavRequest);
264 
265         if (resource != null) {
266             addResponse(
267                 storage, webDavRequest, resource, props, multistatus, depth);
268 
269             String xml = doc.formattedString(StringPool.FOUR_SPACES);
270 
271             if (_log.isDebugEnabled()) {
272                 _log.debug("Response XML\n" + xml);
273             }
274 
275             // Set the status prior to writing the XML
276 
277             int status = WebDAVUtil.SC_MULTI_STATUS;
278 
279             HttpServletResponse response =
280                 webDavRequest.getHttpServletResponse();
281 
282             response.setContentType(ContentTypes.TEXT_XML_UTF8);
283             response.setStatus(status);
284 
285             try {
286                 ServletResponseUtil.write(response, xml);
287             }
288             catch (Exception e) {
289                 if (_log.isWarnEnabled()) {
290                     _log.warn(e);
291                 }
292             }
293 
294             return status;
295         }
296         else {
297             if (_log.isDebugEnabled()) {
298                 _log.debug(
299                     "No resource found for " + storage.getRootPath() +
300                         webDavRequest.getPath());
301             }
302 
303             return HttpServletResponse.SC_NOT_FOUND;
304         }
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 = LogFactoryUtil.getLog(BasePropMethodImpl.class);
355 
356 }