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.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 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 Iterator<Resource> itr = storage.getResources(
347 webDavRequest).iterator();
348
349 while (itr.hasNext()) {
350 resource = itr.next();
351
352 addResponse(webDavRequest, resource, props, multistatusElement);
353 }
354 }
355 }
356
357 protected int writeResponseXML(
358 WebDAVRequest webDavRequest, Set<QName> props)
359 throws Exception {
360
361 WebDAVStorage storage = webDavRequest.getWebDAVStorage();
362
363 long depth = WebDAVUtil.getDepth(webDavRequest.getHttpServletRequest());
364
365 Document document = SAXReaderUtil.createDocument();
366
367 Element multistatusElement = SAXReaderUtil.createElement(
368 createQName("multistatus"));
369
370 document.setRootElement(multistatusElement);
371
372 Resource resource = storage.getResource(webDavRequest);
373
374 if (resource != null) {
375 addResponse(
376 storage, webDavRequest, resource, props, multistatusElement,
377 depth);
378
379 String xml = document.formattedString(StringPool.FOUR_SPACES);
380
381 if (_log.isDebugEnabled()) {
382 _log.debug("Response XML\n" + xml);
383 }
384
385
386
387 int status = WebDAVUtil.SC_MULTI_STATUS;
388
389 HttpServletResponse response =
390 webDavRequest.getHttpServletResponse();
391
392 response.setContentType(ContentTypes.TEXT_XML_UTF8);
393 response.setStatus(status);
394
395 try {
396 ServletResponseUtil.write(response, xml);
397
398 response.flushBuffer();
399 }
400 catch (Exception e) {
401 if (_log.isWarnEnabled()) {
402 _log.warn(e);
403 }
404 }
405
406 return status;
407 }
408 else {
409 if (_log.isDebugEnabled()) {
410 _log.debug(
411 "No resource found for " + storage.getRootPath() +
412 webDavRequest.getPath());
413 }
414
415 return HttpServletResponse.SC_NOT_FOUND;
416 }
417 }
418
419 private static final List<QName> _ALL_COLLECTION_PROPS = Arrays.asList(
420 new QName[] {
421 CREATIONDATE, DISPLAYNAME, GETLASTMODIFIED, GETCONTENTTYPE,
422 LOCKDISCOVERY, RESOURCETYPE
423 });
424
425 private static final List<QName> _ALL_SIMPLE_PROPS = Arrays.asList(
426 new QName[] {
427 CREATIONDATE, DISPLAYNAME, GETLASTMODIFIED, GETCONTENTTYPE,
428 GETCONTENTLENGTH, ISREADONLY, LOCKDISCOVERY, RESOURCETYPE
429 });
430
431 private static Log _log = LogFactoryUtil.getLog(BasePropMethodImpl.class);
432
433 }