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  public abstract class BasePropMethodImpl implements Method {
57  
58      protected void addResponse(
59              WebDAVStorage storage, WebDAVRequest webDavRequest,
60              Resource resource, Set<Tuple> props, Element multistatus,
61              long depth)
62          throws Exception {
63  
64          addResponse(webDavRequest, resource, props, multistatus);
65  
66          if (resource.isCollection() && (depth != 0)) {
67              Iterator<Resource> itr = storage.getResources(
68                  webDavRequest).iterator();
69  
70              while (itr.hasNext()) {
71                  resource = itr.next();
72  
73                  addResponse(webDavRequest, resource, props, multistatus);
74              }
75          }
76      }
77  
78      protected void addResponse(
79              WebDAVRequest webDavRequest, 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             webDavRequest.getCompanyId(), resource.getClassName(),
196             resource.getPrimaryKey());
197 
198         Set<Tuple> customProps = webDavProps.getPropsSet();
199 
200         for (Tuple tuple : props) {
201             String name = (String)tuple.getObject(0);
202             Namespace namespace = (Namespace)tuple.getObject(1);
203 
204             String prefix = namespace.getPrefix();
205             String uri = namespace.getURI();
206 
207             if (customProps.contains(tuple)) {
208                 String text = webDavProps.getText(name, prefix, uri);
209 
210                 DocUtil.add(successProp, name, namespace, text);
211 
212                 hasSuccess = true;
213             }
214             else {
215                 DocUtil.add(failureProp, name, namespace);
216 
217                 hasFailure = true;
218             }
219         }
220 
221         // Clean up propstats
222 
223         if (hasSuccess) {
224             DocUtil.add(
225                 successStat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 200 OK");
226         }
227         else {
228             response.remove(successStat);
229         }
230 
231         if (!hasSuccess && hasFailure) {
232             DocUtil.add(
233                 failureStat, "status", WebDAVUtil.DAV_URI,
234                 "HTTP/1.1 404 Not Found");
235         }
236         else {
237             response.remove(failureStat);
238         }
239     }
240 
241     protected void addResponse(String href, Element multistatus)
242         throws Exception {
243 
244         Element response = DocUtil.add(
245             multistatus, "response", WebDAVUtil.DAV_URI);
246 
247         DocUtil.add(response, "href", WebDAVUtil.DAV_URI, href);
248 
249         Element propstat = DocUtil.add(
250             response, "propstat", WebDAVUtil.DAV_URI);
251 
252         DocUtil.add(
253             propstat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 404 Not Found");
254     }
255 
256     protected int writeResponseXML(
257             WebDAVRequest webDavRequest, Set<Tuple> props)
258         throws Exception {
259 
260         WebDAVStorage storage = webDavRequest.getWebDAVStorage();
261 
262         long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
263 
264         Document doc = SAXReaderUtil.createDocument();
265 
266         Element multistatus = SAXReaderUtil.createElement(
267             SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
268 
269         doc.setRootElement(multistatus);
270 
271         Resource resource = storage.getResource(webDavRequest);
272 
273         if (resource != null) {
274             addResponse(
275                 storage, webDavRequest, resource, props, multistatus, depth);
276 
277             String xml = doc.formattedString(StringPool.FOUR_SPACES);
278 
279             if (_log.isDebugEnabled()) {
280                 _log.debug("Response XML\n" + xml);
281             }
282 
283             // Set the status prior to writing the XML
284 
285             int status = WebDAVUtil.SC_MULTI_STATUS;
286 
287             HttpServletResponse response =
288                 webDavRequest.getHttpServletResponse();
289 
290             response.setContentType(ContentTypes.TEXT_XML_UTF8);
291             response.setStatus(status);
292 
293             if (_log.isInfoEnabled()) {
294                 _log.info("Status code " + status);
295             }
296 
297             try {
298                 ServletResponseUtil.write(response, xml);
299             }
300             catch (Exception e) {
301                 if (_log.isWarnEnabled()) {
302                     _log.warn(e);
303                 }
304             }
305 
306             return -1;
307         }
308         else {
309             if (_log.isDebugEnabled()) {
310                 _log.debug(
311                     "No resource found for " + storage.getRootPath() +
312                         webDavRequest.getPath());
313             }
314 
315             return HttpServletResponse.SC_NOT_FOUND;
316         }
317     }
318 
319     private static final String _ALLPROPS = "allprops";
320 
321     private static final String _CREATIONDATE = "creationdate";
322 
323     private static final String _DISPLAYNAME = "displayname";
324 
325     private static final String _GETLASTMODIFIED = "getlastmodified";
326 
327     private static final String _GETCONTENTTYPE = "getcontenttype";
328 
329     private static final String _GETCONTENTLENGTH = "getcontentlength";
330 
331     private static final String _RESOURCETYPE = "resourcetype";
332 
333     private static final Tuple _ALL_PROPS_PAIR =
334         new Tuple(_ALLPROPS, WebDAVUtil.DAV_URI);
335 
336     private static final Tuple _CREATIONDATE_PAIR =
337         new Tuple(_CREATIONDATE, WebDAVUtil.DAV_URI);
338 
339     private static final Tuple _DISPLAYNAME_PAIR =
340         new Tuple(_DISPLAYNAME, WebDAVUtil.DAV_URI);
341 
342     private static final Tuple _GETLASTMODIFIED_PAIR =
343         new Tuple(_GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
344 
345     private static final Tuple _GETCONTENTTYPE_PAIR =
346         new Tuple(_GETCONTENTTYPE, WebDAVUtil.DAV_URI);
347 
348     private static final Tuple _GETCONTENTLENGTH_PAIR =
349         new Tuple(_GETLASTMODIFIED, WebDAVUtil.DAV_URI);
350 
351     private static final Tuple _RESOURCETYPE_PAIR =
352         new Tuple(_RESOURCETYPE, WebDAVUtil.DAV_URI);
353 
354     private final List<Tuple> _ALL_COLLECTION_PROPS = Arrays.asList(
355         new Tuple[] {
356             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
357             _GETCONTENTTYPE_PAIR, _RESOURCETYPE_PAIR
358         });
359 
360     private final List<Tuple> _ALL_SIMPLE_PROPS = Arrays.asList(
361         new Tuple[] {
362             _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
363             _GETCONTENTTYPE_PAIR, _GETCONTENTLENGTH_PAIR, _RESOURCETYPE_PAIR
364         });
365 
366     private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
367 
368 }