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