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