001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.webdav.methods;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.ContentTypes;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.Tuple;
022    import com.liferay.portal.kernel.webdav.Resource;
023    import com.liferay.portal.kernel.webdav.WebDAVRequest;
024    import com.liferay.portal.kernel.webdav.WebDAVStorage;
025    import com.liferay.portal.kernel.webdav.WebDAVUtil;
026    import com.liferay.portal.kernel.xml.Document;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.Namespace;
029    import com.liferay.portal.kernel.xml.SAXReaderUtil;
030    import com.liferay.portal.model.WebDAVProps;
031    import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
032    import com.liferay.util.servlet.ServletResponseUtil;
033    import com.liferay.util.xml.DocUtil;
034    
035    import java.util.Arrays;
036    import java.util.HashSet;
037    import java.util.Iterator;
038    import java.util.List;
039    import java.util.Set;
040    
041    import javax.servlet.http.HttpServletResponse;
042    
043    /**
044     * @author Alexander Chow
045     */
046    public abstract class BasePropMethodImpl implements Method {
047    
048            protected void addResponse(
049                            WebDAVStorage storage, WebDAVRequest webDavRequest,
050                            Resource resource, Set<Tuple> props, Element multistatus,
051                            long depth)
052                    throws Exception {
053    
054                    addResponse(webDavRequest, resource, props, multistatus);
055    
056                    if (resource.isCollection() && (depth != 0)) {
057                            Iterator<Resource> itr = storage.getResources(
058                                    webDavRequest).iterator();
059    
060                            while (itr.hasNext()) {
061                                    resource = itr.next();
062    
063                                    addResponse(webDavRequest, resource, props, multistatus);
064                            }
065                    }
066            }
067    
068            protected void addResponse(
069                            WebDAVRequest webDavRequest, Resource resource, Set<Tuple> props,
070                            Element multistatus)
071                    throws Exception {
072    
073                    // Make a deep copy of the props
074    
075                    props = new HashSet<Tuple>(props);
076    
077                    // Start building multistatus response
078    
079                    Element response = DocUtil.add(
080                            multistatus, "response", WebDAVUtil.DAV_URI);
081    
082                    DocUtil.add(response, "href", WebDAVUtil.DAV_URI, resource.getHREF());
083    
084                    // Build success and failure propstat elements
085    
086                    Element successStat = DocUtil.add(
087                            response, "propstat", WebDAVUtil.DAV_URI);
088                    Element successProp = DocUtil.add(
089                            successStat, "prop", WebDAVUtil.DAV_URI);
090                    Element failureStat = DocUtil.add(
091                            response, "propstat", WebDAVUtil.DAV_URI);
092                    Element failureProp = DocUtil.add(
093                            failureStat, "prop", WebDAVUtil.DAV_URI);
094    
095                    boolean hasSuccess = false;
096                    boolean hasFailure = false;
097    
098                    // Check DAV properties
099    
100                    if (props.contains(_ALL_PROPS_PAIR)) {
101                            props.remove(_ALL_PROPS_PAIR);
102    
103                            if (resource.isCollection()) {
104                                    props.addAll(_ALL_COLLECTION_PROPS);
105                            }
106                            else {
107                                    props.addAll(_ALL_SIMPLE_PROPS);
108                            }
109                    }
110    
111                    if (props.contains(_CREATIONDATE_PAIR)) {
112                            props.remove(_CREATIONDATE_PAIR);
113    
114                            DocUtil.add(
115                                    successProp, _CREATIONDATE, WebDAVUtil.DAV_URI,
116                                    resource.getCreateDate());
117    
118                            hasSuccess = true;
119                    }
120    
121                    if (props.contains(_DISPLAYNAME_PAIR)) {
122                            props.remove(_DISPLAYNAME_PAIR);
123    
124                            DocUtil.add(
125                                    successProp, _DISPLAYNAME, WebDAVUtil.DAV_URI,
126                                    resource.getDisplayName());
127    
128                            hasSuccess = true;
129                    }
130    
131                    if (props.contains(_GETLASTMODIFIED_PAIR)) {
132                            props.remove(_GETLASTMODIFIED_PAIR);
133    
134                            DocUtil.add(
135                                    successProp, _GETLASTMODIFIED, WebDAVUtil.DAV_URI,
136                                    resource.getModifiedDate());
137    
138                            hasSuccess = true;
139                    }
140    
141                    if (props.contains(_GETCONTENTTYPE_PAIR)) {
142                            props.remove(_GETCONTENTTYPE_PAIR);
143    
144                            DocUtil.add(
145                                    successProp, _GETCONTENTTYPE, WebDAVUtil.DAV_URI,
146                                    resource.getContentType());
147    
148                            hasSuccess = true;
149                    }
150    
151                    if (props.contains(_GETCONTENTLENGTH_PAIR)) {
152                            props.remove(_GETCONTENTLENGTH_PAIR);
153    
154                            if (!resource.isCollection()) {
155                                    DocUtil.add(
156                                            successProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI,
157                                            resource.getSize());
158    
159                                    hasSuccess = true;
160                            }
161                            else {
162                                    DocUtil.add(
163                                            failureProp, _GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
164    
165                                    hasFailure = true;
166                            }
167                    }
168    
169                    if (props.contains(_RESOURCETYPE_PAIR)) {
170                            props.remove(_RESOURCETYPE_PAIR);
171    
172                            Element resourceType =
173                                    DocUtil.add(successProp, _RESOURCETYPE, WebDAVUtil.DAV_URI);
174    
175                            if (resource.isCollection()) {
176                                    DocUtil.add(resourceType, "collection", WebDAVUtil.DAV_URI);
177                            }
178    
179                            hasSuccess = true;
180                    }
181    
182                    // Check remaining properties against custom properties
183    
184                    WebDAVProps webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
185                            webDavRequest.getCompanyId(), resource.getClassName(),
186                            resource.getPrimaryKey());
187    
188                    Set<Tuple> customProps = webDavProps.getPropsSet();
189    
190                    for (Tuple tuple : props) {
191                            String name = (String)tuple.getObject(0);
192                            Namespace namespace = (Namespace)tuple.getObject(1);
193    
194                            String prefix = namespace.getPrefix();
195                            String uri = namespace.getURI();
196    
197                            if (customProps.contains(tuple)) {
198                                    String text = webDavProps.getText(name, prefix, uri);
199    
200                                    DocUtil.add(successProp, name, namespace, text);
201    
202                                    hasSuccess = true;
203                            }
204                            else {
205                                    DocUtil.add(failureProp, name, namespace);
206    
207                                    hasFailure = true;
208                            }
209                    }
210    
211                    // Clean up propstats
212    
213                    if (hasSuccess) {
214                            DocUtil.add(
215                                    successStat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 200 OK");
216                    }
217                    else {
218                            response.remove(successStat);
219                    }
220    
221                    if (!hasSuccess && hasFailure) {
222                            DocUtil.add(
223                                    failureStat, "status", WebDAVUtil.DAV_URI,
224                                    "HTTP/1.1 404 Not Found");
225                    }
226                    else {
227                            response.remove(failureStat);
228                    }
229            }
230    
231            protected void addResponse(String href, Element multistatus)
232                    throws Exception {
233    
234                    Element response = DocUtil.add(
235                            multistatus, "response", WebDAVUtil.DAV_URI);
236    
237                    DocUtil.add(response, "href", WebDAVUtil.DAV_URI, href);
238    
239                    Element propstat = DocUtil.add(
240                            response, "propstat", WebDAVUtil.DAV_URI);
241    
242                    DocUtil.add(
243                            propstat, "status", WebDAVUtil.DAV_URI, "HTTP/1.1 404 Not Found");
244            }
245    
246            protected int writeResponseXML(
247                            WebDAVRequest webDavRequest, Set<Tuple> props)
248                    throws Exception {
249    
250                    WebDAVStorage storage = webDavRequest.getWebDAVStorage();
251    
252                    long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
253    
254                    Document doc = SAXReaderUtil.createDocument();
255    
256                    Element multistatus = SAXReaderUtil.createElement(
257                            SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
258    
259                    doc.setRootElement(multistatus);
260    
261                    Resource resource = storage.getResource(webDavRequest);
262    
263                    if (resource != null) {
264                            addResponse(
265                                    storage, webDavRequest, resource, props, multistatus, depth);
266    
267                            String xml = doc.formattedString(StringPool.FOUR_SPACES);
268    
269                            if (_log.isDebugEnabled()) {
270                                    _log.debug("Response XML\n" + xml);
271                            }
272    
273                            // Set the status prior to writing the XML
274    
275                            int status = WebDAVUtil.SC_MULTI_STATUS;
276    
277                            HttpServletResponse response =
278                                    webDavRequest.getHttpServletResponse();
279    
280                            response.setContentType(ContentTypes.TEXT_XML_UTF8);
281                            response.setStatus(status);
282    
283                            try {
284                                    ServletResponseUtil.write(response, xml);
285                            }
286                            catch (Exception e) {
287                                    if (_log.isWarnEnabled()) {
288                                            _log.warn(e);
289                                    }
290                            }
291    
292                            return status;
293                    }
294                    else {
295                            if (_log.isDebugEnabled()) {
296                                    _log.debug(
297                                            "No resource found for " + storage.getRootPath() +
298                                                    webDavRequest.getPath());
299                            }
300    
301                            return HttpServletResponse.SC_NOT_FOUND;
302                    }
303            }
304    
305            private static final String _ALLPROPS = "allprops";
306    
307            private static final String _CREATIONDATE = "creationdate";
308    
309            private static final String _DISPLAYNAME = "displayname";
310    
311            private static final String _GETLASTMODIFIED = "getlastmodified";
312    
313            private static final String _GETCONTENTTYPE = "getcontenttype";
314    
315            private static final String _GETCONTENTLENGTH = "getcontentlength";
316    
317            private static final String _RESOURCETYPE = "resourcetype";
318    
319            private static final Tuple _ALL_PROPS_PAIR =
320                    new Tuple(_ALLPROPS, WebDAVUtil.DAV_URI);
321    
322            private static final Tuple _CREATIONDATE_PAIR =
323                    new Tuple(_CREATIONDATE, WebDAVUtil.DAV_URI);
324    
325            private static final Tuple _DISPLAYNAME_PAIR =
326                    new Tuple(_DISPLAYNAME, WebDAVUtil.DAV_URI);
327    
328            private static final Tuple _GETLASTMODIFIED_PAIR =
329                    new Tuple(_GETLASTMODIFIED, WebDAVUtil.DAV_URI);
330    
331            private static final Tuple _GETCONTENTTYPE_PAIR =
332                    new Tuple(_GETCONTENTTYPE, WebDAVUtil.DAV_URI);
333    
334            private static final Tuple _GETCONTENTLENGTH_PAIR =
335                    new Tuple(_GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
336    
337            private static final Tuple _RESOURCETYPE_PAIR =
338                    new Tuple(_RESOURCETYPE, WebDAVUtil.DAV_URI);
339    
340            private final List<Tuple> _ALL_COLLECTION_PROPS = Arrays.asList(
341                    new Tuple[] {
342                            _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
343                            _GETCONTENTTYPE_PAIR, _RESOURCETYPE_PAIR
344                    });
345    
346            private final List<Tuple> _ALL_SIMPLE_PROPS = Arrays.asList(
347                    new Tuple[] {
348                            _CREATIONDATE_PAIR, _DISPLAYNAME_PAIR, _GETLASTMODIFIED_PAIR,
349                            _GETCONTENTTYPE_PAIR, _GETCONTENTLENGTH_PAIR, _RESOURCETYPE_PAIR
350                    });
351    
352            private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
353    
354    }