001
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.Time;
022 import com.liferay.portal.kernel.util.Tuple;
023 import com.liferay.portal.kernel.webdav.Resource;
024 import com.liferay.portal.kernel.webdav.WebDAVRequest;
025 import com.liferay.portal.kernel.webdav.WebDAVStorage;
026 import com.liferay.portal.kernel.webdav.WebDAVUtil;
027 import com.liferay.portal.kernel.xml.Document;
028 import com.liferay.portal.kernel.xml.Element;
029 import com.liferay.portal.kernel.xml.Namespace;
030 import com.liferay.portal.kernel.xml.QName;
031 import com.liferay.portal.kernel.xml.SAXReaderUtil;
032 import com.liferay.portal.model.Lock;
033 import com.liferay.portal.model.WebDAVProps;
034 import com.liferay.portal.service.WebDAVPropsLocalServiceUtil;
035 import com.liferay.util.servlet.ServletResponseUtil;
036 import com.liferay.util.xml.DocUtil;
037
038 import java.util.Arrays;
039 import java.util.HashSet;
040 import java.util.Iterator;
041 import java.util.List;
042 import java.util.Set;
043
044 import javax.servlet.http.HttpServletResponse;
045
046
049 public abstract class BasePropMethodImpl implements Method {
050
051 public static final String ALLPROP = "allprop";
052
053 public static final Tuple ALLPROP_PAIR = new Tuple(
054 ALLPROP, WebDAVUtil.DAV_URI);
055
056 public static final String CREATIONDATE = "creationdate";
057
058 public static final Tuple CREATIONDATE_PAIR = new Tuple(
059 CREATIONDATE, WebDAVUtil.DAV_URI);
060
061 public static final String DISPLAYNAME = "displayname";
062
063 public static final Tuple DISPLAYNAME_PAIR = new Tuple(
064 DISPLAYNAME, WebDAVUtil.DAV_URI);
065
066 public static final String GETCONTENTLENGTH = "getcontentlength";
067
068 public static final Tuple GETCONTENTLENGTH_PAIR = new Tuple(
069 GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
070
071 public static final String GETCONTENTTYPE = "getcontenttype";
072
073 public static final Tuple GETCONTENTTYPE_PAIR = new Tuple(
074 GETCONTENTTYPE, WebDAVUtil.DAV_URI);
075
076 public static final String GETLASTMODIFIED = "getlastmodified";
077
078 public static final Tuple GETLASTMODIFIED_PAIR = new Tuple(
079 GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
080
081 public static final String LOCKDISCOVERY = "lockdiscovery";
082
083 public static final Tuple LOCKDISCOVERY_PAIR = new Tuple(
084 LOCKDISCOVERY, WebDAVUtil.DAV_URI);
085
086 public static final String RESOURCETYPE = "resourcetype";
087
088 public static final Tuple RESOURCETYPE_PAIR = new Tuple(
089 RESOURCETYPE, WebDAVUtil.DAV_URI);
090
091 protected Element addElement(Element element, String name) {
092 QName qName = SAXReaderUtil.createQName(name, WebDAVUtil.DAV_URI);
093
094 return element.addElement(qName);
095 }
096
097 protected Element addElement(Element element, String name1, String name2) {
098 Element childElement = addElement(element, name1);
099
100 return addElement(childElement, name2);
101 }
102
103 protected void addResponse(String href, Element multistatusElement)
104 throws Exception {
105
106 Element responseElement = DocUtil.add(
107 multistatusElement, "response", WebDAVUtil.DAV_URI);
108
109 DocUtil.add(responseElement, "href", WebDAVUtil.DAV_URI, href);
110
111 Element propstatElement = DocUtil.add(
112 responseElement, "propstat", WebDAVUtil.DAV_URI);
113
114 DocUtil.add(
115 propstatElement, "status", WebDAVUtil.DAV_URI,
116 "HTTP/1.1 404 Not Found");
117 }
118
119 protected void addResponse(
120 WebDAVRequest webDavRequest, Resource resource, Set<Tuple> props,
121 Element multistatus)
122 throws Exception {
123
124
125
126 props = new HashSet<Tuple>(props);
127
128
129
130 Element responseElement = DocUtil.add(
131 multistatus, "response", WebDAVUtil.DAV_URI);
132
133 DocUtil.add(
134 responseElement, "href", WebDAVUtil.DAV_URI, resource.getHREF());
135
136
137
138 Element successStatElement = DocUtil.add(
139 responseElement, "propstat", WebDAVUtil.DAV_URI);
140 Element successPropElement = DocUtil.add(
141 successStatElement, "prop", WebDAVUtil.DAV_URI);
142 Element failureStatElement = DocUtil.add(
143 responseElement, "propstat", WebDAVUtil.DAV_URI);
144 Element failurePropElement = DocUtil.add(
145 failureStatElement, "prop", WebDAVUtil.DAV_URI);
146
147 boolean hasSuccess = false;
148 boolean hasFailure = false;
149
150
151
152 if (props.contains(ALLPROP_PAIR)) {
153 props.remove(ALLPROP_PAIR);
154
155 if (resource.isCollection()) {
156 props.addAll(_ALL_COLLECTION_PROPS);
157 }
158 else {
159 props.addAll(_ALL_SIMPLE_PROPS);
160 }
161 }
162
163 if (props.contains(CREATIONDATE_PAIR)) {
164 props.remove(CREATIONDATE_PAIR);
165
166 DocUtil.add(
167 successPropElement, CREATIONDATE, WebDAVUtil.DAV_URI,
168 resource.getCreateDate());
169
170 hasSuccess = true;
171 }
172
173 if (props.contains(DISPLAYNAME_PAIR)) {
174 props.remove(DISPLAYNAME_PAIR);
175
176 DocUtil.add(
177 successPropElement, DISPLAYNAME, WebDAVUtil.DAV_URI,
178 resource.getDisplayName());
179
180 hasSuccess = true;
181 }
182
183 if (props.contains(GETLASTMODIFIED_PAIR)) {
184 props.remove(GETLASTMODIFIED_PAIR);
185
186 DocUtil.add(
187 successPropElement, GETLASTMODIFIED, WebDAVUtil.DAV_URI,
188 resource.getModifiedDate());
189
190 hasSuccess = true;
191 }
192
193 if (props.contains(GETCONTENTTYPE_PAIR)) {
194 props.remove(GETCONTENTTYPE_PAIR);
195
196 DocUtil.add(
197 successPropElement, GETCONTENTTYPE, WebDAVUtil.DAV_URI,
198 resource.getContentType());
199
200 hasSuccess = true;
201 }
202
203 if (props.contains(GETCONTENTLENGTH_PAIR)) {
204 props.remove(GETCONTENTLENGTH_PAIR);
205
206 if (!resource.isCollection()) {
207 DocUtil.add(
208 successPropElement, GETCONTENTLENGTH, WebDAVUtil.DAV_URI,
209 resource.getSize());
210
211 hasSuccess = true;
212 }
213 else {
214 DocUtil.add(
215 failurePropElement, GETCONTENTLENGTH, WebDAVUtil.DAV_URI);
216
217 hasFailure = true;
218 }
219 }
220
221 if (props.contains(LOCKDISCOVERY_PAIR)) {
222 props.remove(LOCKDISCOVERY_PAIR);
223
224 Lock lock = resource.getLock();
225
226 if (lock != null) {
227 long now = System.currentTimeMillis();
228
229 long timeRemaining =
230 (lock.getExpirationDate().getTime() - now) / Time.SECOND;
231
232 if (timeRemaining <= 0) {
233 timeRemaining = 1;
234 }
235
236 Element lockDiscoveryElement = addElement(
237 successPropElement, LOCKDISCOVERY);
238
239 Element activeLockElement = addElement(
240 lockDiscoveryElement, "activelock");
241
242 addElement(activeLockElement, "locktype", "write");
243 addElement(activeLockElement, "lockscope", "exclusive");
244
245 if (resource.isCollection()) {
246 DocUtil.add(
247 activeLockElement, "depth", WebDAVUtil.DAV_URI,
248 "Infinity");
249 }
250
251 DocUtil.add(
252 activeLockElement, "owner", WebDAVUtil.DAV_URI,
253 lock.getOwner());
254 DocUtil.add(
255 activeLockElement, "timeout", WebDAVUtil.DAV_URI,
256 "Second-" + timeRemaining);
257
258 if (webDavRequest.getUserId() == lock.getUserId()) {
259 Element lockTokenElement = addElement(
260 activeLockElement, "locktoken", "href");
261
262 lockTokenElement.addText(
263 "opaquelocktoken:" + lock.getUuid());
264 }
265
266 hasSuccess = true;
267 }
268 else {
269 DocUtil.add(
270 failurePropElement, LOCKDISCOVERY, WebDAVUtil.DAV_URI);
271
272 hasFailure = true;
273 }
274 }
275
276 if (props.contains(RESOURCETYPE_PAIR)) {
277 props.remove(RESOURCETYPE_PAIR);
278
279 Element resourceTypeElement = DocUtil.add(
280 successPropElement, RESOURCETYPE, WebDAVUtil.DAV_URI);
281
282 if (resource.isCollection()) {
283 DocUtil.add(
284 resourceTypeElement, "collection", WebDAVUtil.DAV_URI);
285 }
286
287 hasSuccess = true;
288 }
289
290
291
292 WebDAVProps webDavProps = WebDAVPropsLocalServiceUtil.getWebDAVProps(
293 webDavRequest.getCompanyId(), resource.getClassName(),
294 resource.getPrimaryKey());
295
296 Set<Tuple> customProps = webDavProps.getPropsSet();
297
298 for (Tuple tuple : props) {
299 String name = (String)tuple.getObject(0);
300 Namespace namespace = (Namespace)tuple.getObject(1);
301
302 String prefix = namespace.getPrefix();
303 String uri = namespace.getURI();
304
305 if (customProps.contains(tuple)) {
306 String text = webDavProps.getText(name, prefix, uri);
307
308 DocUtil.add(successPropElement, name, namespace, text);
309
310 hasSuccess = true;
311 }
312 else {
313 DocUtil.add(failurePropElement, name, namespace);
314
315 hasFailure = true;
316 }
317 }
318
319
320
321 if (hasSuccess) {
322 DocUtil.add(
323 successStatElement, "status", WebDAVUtil.DAV_URI,
324 "HTTP/1.1 200 OK");
325 }
326 else {
327 responseElement.remove(successStatElement);
328 }
329
330 if (!hasSuccess && hasFailure) {
331 DocUtil.add(
332 failureStatElement, "status", WebDAVUtil.DAV_URI,
333 "HTTP/1.1 404 Not Found");
334 }
335 else {
336 responseElement.remove(failureStatElement);
337 }
338 }
339
340 protected void addResponse(
341 WebDAVStorage storage, WebDAVRequest webDavRequest,
342 Resource resource, Set<Tuple> props, Element multistatusElement,
343 long depth)
344 throws Exception {
345
346 addResponse(webDavRequest, resource, props, multistatusElement);
347
348 if (resource.isCollection() && (depth != 0)) {
349 Iterator<Resource> itr = storage.getResources(
350 webDavRequest).iterator();
351
352 while (itr.hasNext()) {
353 resource = itr.next();
354
355 addResponse(
356 webDavRequest, resource, props, multistatusElement);
357 }
358 }
359 }
360
361 protected int writeResponseXML(
362 WebDAVRequest webDavRequest, Set<Tuple> props)
363 throws Exception {
364
365 WebDAVStorage storage = webDavRequest.getWebDAVStorage();
366
367 long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
368
369 Document document = SAXReaderUtil.createDocument();
370
371 Element multistatusElement = SAXReaderUtil.createElement(
372 SAXReaderUtil.createQName("multistatus", WebDAVUtil.DAV_URI));
373
374 document.setRootElement(multistatusElement);
375
376 Resource resource = storage.getResource(webDavRequest);
377
378 if (resource != null) {
379 addResponse(
380 storage, webDavRequest, resource, props, multistatusElement,
381 depth);
382
383 String xml = document.formattedString(StringPool.FOUR_SPACES);
384
385 if (_log.isDebugEnabled()) {
386 _log.debug("Response XML\n" + xml);
387 }
388
389
390
391 int status = WebDAVUtil.SC_MULTI_STATUS;
392
393 HttpServletResponse response =
394 webDavRequest.getHttpServletResponse();
395
396 response.setContentType(ContentTypes.TEXT_XML_UTF8);
397 response.setStatus(status);
398
399 try {
400 ServletResponseUtil.write(response, xml);
401 }
402 catch (Exception e) {
403 if (_log.isWarnEnabled()) {
404 _log.warn(e);
405 }
406 }
407
408 return status;
409 }
410 else {
411 if (_log.isDebugEnabled()) {
412 _log.debug(
413 "No resource found for " + storage.getRootPath() +
414 webDavRequest.getPath());
415 }
416
417 return HttpServletResponse.SC_NOT_FOUND;
418 }
419 }
420
421 private static final List<Tuple> _ALL_COLLECTION_PROPS = Arrays.asList(
422 new Tuple[] {
423 CREATIONDATE_PAIR, DISPLAYNAME_PAIR, GETLASTMODIFIED_PAIR,
424 GETCONTENTTYPE_PAIR, LOCKDISCOVERY_PAIR, RESOURCETYPE_PAIR
425 });
426
427 private static final List<Tuple> _ALL_SIMPLE_PROPS = Arrays.asList(
428 new Tuple[] {
429 CREATIONDATE_PAIR, DISPLAYNAME_PAIR, GETLASTMODIFIED_PAIR,
430 GETCONTENTTYPE_PAIR, GETCONTENTLENGTH_PAIR, LOCKDISCOVERY_PAIR,
431 RESOURCETYPE_PAIR
432 });
433
434 private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
435
436 }