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