1
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.Time;
22 import com.liferay.portal.kernel.util.Tuple;
23 import com.liferay.portal.kernel.xml.Document;
24 import com.liferay.portal.kernel.xml.Element;
25 import com.liferay.portal.kernel.xml.Namespace;
26 import com.liferay.portal.kernel.xml.QName;
27 import com.liferay.portal.kernel.xml.SAXReaderUtil;
28 import com.liferay.portal.model.Lock;
29 import com.liferay.portal.model.WebDAVProps;
30 import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
31 import com.liferay.portal.webdav.Resource;
32 import com.liferay.portal.webdav.WebDAVRequest;
33 import com.liferay.portal.webdav.WebDAVStorage;
34 import com.liferay.portal.webdav.WebDAVUtil;
35 import com.liferay.util.servlet.ServletResponseUtil;
36 import com.liferay.util.xml.DocUtil;
37
38 import java.util.Arrays;
39 import java.util.HashSet;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Set;
43
44 import javax.servlet.http.HttpServletResponse;
45
46
51 public abstract class BasePropMethodImpl implements Method {
52
53 public static final String ALLPROP = "allprop";
54
55 public static final Tuple ALLPROP_PAIR = new Tuple(
56 ALLPROP, WebDAVUtil.DAV_URI);
57
58 public static final String CREATIONDATE = "creationdate";
59
60 public static final Tuple CREATIONDATE_PAIR = new Tuple(
61 CREATIONDATE, WebDAVUtil.DAV_URI);
62
63 public static final String DISPLAYNAME = "displayname";
64
65 public static final Tuple DISPLAYNAME_PAIR = new Tuple(
66 DISPLAYNAME, WebDAVUtil.DAV_URI);
67
68 public static final String GETCONTENTLENGTH = "getcontentlength";
69
70 public static final Tuple GETCONTENTLENGTH_PAIR = new Tuple(
71 GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
72
73 public static final String GETCONTENTTYPE = "getcontenttype";
74
75 public static final Tuple GETCONTENTTYPE_PAIR = new Tuple(
76 GETCONTENTTYPE, WebDAVUtil.DAV_URI);
77
78 public static final String GETLASTMODIFIED = "getlastmodified";
79
80 public static final Tuple GETLASTMODIFIED_PAIR = new Tuple(
81 GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
82
83 public static final String LOCKDISCOVERY = "lockdiscovery";
84
85 public static final Tuple LOCKDISCOVERY_PAIR = new Tuple(
86 LOCKDISCOVERY, WebDAVUtil.DAV_URI);
87
88 public static final String RESOURCETYPE = "resourcetype";
89
90 public static final Tuple RESOURCETYPE_PAIR = new Tuple(
91 RESOURCETYPE, WebDAVUtil.DAV_URI);
92
93 protected Element addElement(Element element, String name) {
94 QName qName = SAXReaderUtil.createQName(name, WebDAVUtil.DAV_URI);
95
96 return element.addElement(qName);
97 }
98
99 protected Element addElement(Element element, String name1, String name2) {
100 Element childElement = addElement(element, name1);
101
102 return addElement(childElement, name2);
103 }
104
105 protected void addResponse(String href, Element multistatusElement)
106 throws Exception {
107
108 Element responseElement = DocUtil.add(
109 multistatusElement, "response", WebDAVUtil.DAV_URI);
110
111 DocUtil.add(responseElement, "href", WebDAVUtil.DAV_URI, href);
112
113 Element propstatElement = DocUtil.add(
114 responseElement, "propstat", WebDAVUtil.DAV_URI);
115
116 DocUtil.add(
117 propstatElement, "status", WebDAVUtil.DAV_URI,
118 "HTTP/1.1 404 Not Found");
119 }
120
121 protected void addResponse(
122 WebDAVRequest webDavRequest, Resource resource, Set<Tuple> props,
123 Element multistatus)
124 throws Exception {
125
126
128 props = new HashSet<Tuple>(props);
129
130
132 Element responseElement = DocUtil.add(
133 multistatus, "response", WebDAVUtil.DAV_URI);
134
135 DocUtil.add(
136 responseElement, "href", WebDAVUtil.DAV_URI, resource.getHREF());
137
138
140 Element successStatElement = DocUtil.add(
141 responseElement, "propstat", WebDAVUtil.DAV_URI);
142 Element successPropElement = DocUtil.add(
143 successStatElement, "prop", WebDAVUtil.DAV_URI);
144 Element failureStatElement = DocUtil.add(
145 responseElement, "propstat", WebDAVUtil.DAV_URI);
146 Element failurePropElement = DocUtil.add(
147 failureStatElement, "prop", WebDAVUtil.DAV_URI);
148
149 boolean hasSuccess = false;
150 boolean hasFailure = false;
151
152
154 if (props.contains(ALLPROP_PAIR)) {
155 props.remove(ALLPROP_PAIR);
156
157 if (resource.isCollection()) {
158 props.addAll(_ALL_COLLECTION_PROPS);
159 }
160 else {
161 props.addAll(_ALL_SIMPLE_PROPS);
162 }
163 }
164
165 if (props.contains(CREATIONDATE_PAIR)) {
166 props.remove(CREATIONDATE_PAIR);
167
168 DocUtil.add(
169 successPropElement, CREATIONDATE, WebDAVUtil.DAV_URI,
170 resource.getCreateDate());
171
172 hasSuccess = true;
173 }
174
175 if (props.contains(DISPLAYNAME_PAIR)) {
176 props.remove(DISPLAYNAME_PAIR);
177
178 DocUtil.add(
179 successPropElement, DISPLAYNAME, WebDAVUtil.DAV_URI,
180 resource.getDisplayName());
181
182 hasSuccess = true;
183 }
184
185 if (props.contains(GETLASTMODIFIED_PAIR)) {
186 props.remove(GETLASTMODIFIED_PAIR);
187
188 DocUtil.add(
189 successPropElement, GETLASTMODIFIED, WebDAVUtil.DAV_URI,
190 resource.getModifiedDate());
191
192 hasSuccess = true;
193 }
194
195 if (props.contains(GETCONTENTTYPE_PAIR)) {
196 props.remove(GETCONTENTTYPE_PAIR);
197
198 DocUtil.add(
199 successPropElement, GETCONTENTTYPE, WebDAVUtil.DAV_URI,
200 resource.getContentType());
201
202 hasSuccess = true;
203 }
204
205 if (props.contains(GETCONTENTLENGTH_PAIR)) {
206 props.remove(GETCONTENTLENGTH_PAIR);
207
208 if (!resource.isCollection()) {
209 DocUtil.add(
210 successPropElement, GETCONTENTLENGTH, WebDAVUtil.DAV_URI,
211 resource.getSize());
212
213 hasSuccess = true;
214 }
215 else {
216 DocUtil.add(
217 failurePropElement, GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
218
219 hasFailure = true;
220 }
221 }
222
223 if (props.contains(LOCKDISCOVERY_PAIR)) {
224 props.remove(LOCKDISCOVERY_PAIR);
225
226 Lock lock = resource.getLock();
227
228 if (lock != null) {
229 long now = System.currentTimeMillis();
230
231 long timeRemaining =
232 (lock.getExpirationDate().getTime() - now) / Time.SECOND;
233
234 if (timeRemaining <= 0) {
235 timeRemaining = 1;
236 }
237
238 Element lockDiscoveryElement = addElement(
239 successPropElement, LOCKDISCOVERY);
240
241 Element activeLockElement = addElement(
242 lockDiscoveryElement, "activelock");
243
244 addElement(activeLockElement, "locktype", "write");
245 addElement(activeLockElement, "lockscope", "exclusive");
246
247 if (resource.isCollection()) {
248 DocUtil.add(
249 activeLockElement, "depth", WebDAVUtil.DAV_URI,
250 "Infinity");
251 }
252
253 DocUtil.add(
254 activeLockElement, "owner", WebDAVUtil.DAV_URI,
255 lock.getOwner());
256 DocUtil.add(
257 activeLockElement, "timeout", WebDAVUtil.DAV_URI,
258 "Second-" + timeRemaining);
259
260 if (webDavRequest.getUserId() == lock.getUserId()) {
261 Element lockTokenElement = addElement(
262 activeLockElement, "locktoken", "href");
263
264 lockTokenElement.addText(
265 "opaquelocktoken:" + lock.getUuid());
266 }
267
268 hasSuccess = true;
269 }
270 else {
271 DocUtil.add(
272 failurePropElement, LOCKDISCOVERY, WebDAVUtil.DAV_URI);
273
274 hasFailure = true;
275 }
276 }
277
278 if (props.contains(RESOURCETYPE_PAIR)) {
279 props.remove(RESOURCETYPE_PAIR);
280
281 Element resourceTypeElement = DocUtil.add(
282 successPropElement, RESOURCETYPE, WebDAVUtil.DAV_URI);
283
284 if (resource.isCollection()) {
285 DocUtil.add(
286 resourceTypeElement, "collection", WebDAVUtil.DAV_URI);
287 }
288
289 hasSuccess = true;
290 }
291
292
294 WebDAVProps webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
295 webDavRequest.getCompanyId(), resource.getClassName(),
296 resource.getPrimaryKey());
297
298 Set<Tuple> customProps = webDavProps.getPropsSet();
299
300 for (Tuple tuple : props) {
301 String name = (String)tuple.getObject(0);
302 Namespace namespace = (Namespace)tuple.getObject(1);
303
304 String prefix = namespace.getPrefix();
305 String uri = namespace.getURI();
306
307 if (customProps.contains(tuple)) {
308 String text = webDavProps.getText(name, prefix, uri);
309
310 DocUtil.add(successPropElement, name, namespace, text);
311
312 hasSuccess = true;
313 }
314 else {
315 DocUtil.add(failurePropElement, name, namespace);
316
317 hasFailure = true;
318 }
319 }
320
321
323 if (hasSuccess) {
324 DocUtil.add(
325 successStatElement, "status", WebDAVUtil.DAV_URI,
326 "HTTP/1.1 200 OK");
327 }
328 else {
329 responseElement.remove(successStatElement);
330 }
331
332 if (!hasSuccess && hasFailure) {
333 DocUtil.add(
334 failureStatElement, "status", WebDAVUtil.DAV_URI,
335 "HTTP/1.1 404 Not Found");
336 }
337 else {
338 responseElement.remove(failureStatElement);
339 }
340 }
341
342 protected void addResponse(
343 WebDAVStorage storage, WebDAVRequest webDavRequest,
344 Resource resource, Set<Tuple> props, Element multistatusElement,
345 long depth)
346 throws Exception {
347
348 addResponse(webDavRequest, resource, props, multistatusElement);
349
350 if (resource.isCollection() && (depth != 0)) {
351 Iterator<Resource> itr = storage.getResources(
352 webDavRequest).iterator();
353
354 while (itr.hasNext()) {
355 resource = itr.next();
356
357 addResponse(
358 webDavRequest, resource, props, multistatusElement);
359 }
360 }
361 }
362
363 protected int writeResponseXML(
364 WebDAVRequest webDavRequest, Set<Tuple> props)
365 throws Exception {
366
367 WebDAVStorage storage = webDavRequest.getWebDAVStorage();
368
369 long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
370
371 Document document = SAXReaderUtil.createDocument();
372
373 Element multistatusElement = SAXReaderUtil.createElement(
374 SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
375
376 document.setRootElement(multistatusElement);
377
378 Resource resource = storage.getResource(webDavRequest);
379
380 if (resource != null) {
381 addResponse(
382 storage, webDavRequest, resource, props, multistatusElement,
383 depth);
384
385 String xml = document.formattedString(StringPool.FOUR_SPACES);
386
387 if (_log.isDebugEnabled()) {
388 _log.debug("Response XML\n" + xml);
389 }
390
391
393 int status = WebDAVUtil.SC_MULTI_STATUS;
394
395 HttpServletResponse response =
396 webDavRequest.getHttpServletResponse();
397
398 response.setContentType(ContentTypes.TEXT_XML_UTF8);
399 response.setStatus(status);
400
401 try {
402 ServletResponseUtil.write(response, xml);
403
404 response.flushBuffer();
405 }
406 catch (Exception e) {
407 if (_log.isWarnEnabled()) {
408 _log.warn(e);
409 }
410 }
411
412 return status;
413 }
414 else {
415 if (_log.isDebugEnabled()) {
416 _log.debug(
417 "No resource found for " + storage.getRootPath() +
418 webDavRequest.getPath());
419 }
420
421 return HttpServletResponse.SC_NOT_FOUND;
422 }
423 }
424
425 private static final List<Tuple> _ALL_COLLECTION_PROPS = Arrays.asList(
426 new Tuple[] {
427 CREATIONDATE_PAIR, DISPLAYNAME_PAIR, GETLASTMODIFIED_PAIR,
428 GETCONTENTTYPE_PAIR, LOCKDISCOVERY_PAIR, RESOURCETYPE_PAIR
429 });
430
431 private static final List<Tuple> _ALL_SIMPLE_PROPS = Arrays.asList(
432 new Tuple[] {
433 CREATIONDATE_PAIR, DISPLAYNAME_PAIR, GETLASTMODIFIED_PAIR,
434 GETCONTENTTYPE_PAIR, GETCONTENTLENGTH_PAIR, LOCKDISCOVERY_PAIR,
435 RESOURCETYPE_PAIR
436 });
437
438 private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
439
440 }