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