1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.danube.webdav;
14
15 import org.abstracthorizon.danube.adapter.Adaptable;
16 import org.abstracthorizon.danube.http.BaseReflectionHTTPConnectionHandler;
17 import org.abstracthorizon.danube.http.HTTPBufferedInputStream;
18 import org.abstracthorizon.danube.http.HTTPConnection;
19 import org.abstracthorizon.danube.http.Status;
20 import org.abstracthorizon.danube.http.util.IOUtils;
21 import org.abstracthorizon.danube.http.util.Ranges;
22 import org.abstracthorizon.danube.support.RuntimeIOException;
23 import org.abstracthorizon.danube.support.logging.LoggingConnection;
24 import org.abstracthorizon.danube.webdav.lock.Lock;
25 import org.abstracthorizon.danube.webdav.lock.LockingMechanism;
26 import org.abstracthorizon.danube.webdav.util.CollectionHTMLRenderer;
27 import org.abstracthorizon.danube.webdav.util.Depth;
28 import org.abstracthorizon.danube.webdav.util.IF;
29 import org.abstracthorizon.danube.webdav.util.SimpleHTMLCollectionRenderer;
30 import org.abstracthorizon.danube.webdav.util.Timeout;
31 import org.abstracthorizon.danube.webdav.util.URIUtils;
32 import org.abstracthorizon.danube.webdav.xml.WebDAVXMLHandler;
33 import org.abstracthorizon.danube.webdav.xml.dav.RequestProp;
34 import org.abstracthorizon.danube.webdav.xml.dav.request.LockInfo;
35 import org.abstracthorizon.danube.webdav.xml.dav.request.PropFind;
36 import org.abstracthorizon.danube.webdav.xml.dav.request.PropertyBehavior;
37 import org.abstracthorizon.danube.webdav.xml.dav.request.PropertyUpdate;
38 import org.abstracthorizon.danube.webdav.xml.dav.request.properties.RequestProperty;
39 import org.abstracthorizon.danube.webdav.xml.dav.response.MultiStatus;
40 import org.abstracthorizon.danube.webdav.xml.dav.response.Propstat;
41 import org.abstracthorizon.danube.webdav.xml.dav.response.Response;
42 import org.abstracthorizon.danube.webdav.xml.dav.response.properties.LockDiscovery;
43 import org.abstracthorizon.danube.webdav.xml.dav.response.properties.ResponseProperty;
44
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.io.OutputStream;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.StringTokenizer;
54
55 import javax.xml.parsers.ParserConfigurationException;
56 import javax.xml.parsers.SAXParser;
57 import javax.xml.parsers.SAXParserFactory;
58
59 import org.xml.sax.InputSource;
60 import org.xml.sax.SAXException;
61 import org.xml.sax.XMLReader;
62
63
64
65
66
67
68
69 public class BaseWebDAVResourceConnectionHandler extends BaseReflectionHTTPConnectionHandler {
70
71
72 public static final Status STATUS_LOCKED = new Status("423", "Locked");
73
74
75 public static final Status STATUS_FAILED_DEPENDENCY = new Status("424", "Failed Dependency");
76
77
78 protected ResourceAdapter adapter;
79
80
81 protected int bufferSize = 2048;
82
83
84 protected CollectionHTMLRenderer collectionRenderer = new SimpleHTMLCollectionRenderer();
85
86
87 protected boolean readOnly = false;
88
89
90
91
92 public BaseWebDAVResourceConnectionHandler() {
93 }
94
95
96
97
98
99
100 public BaseWebDAVResourceConnectionHandler(ResourceAdapter webDAVAdapter) {
101 setWebDAVResourceAdapter(webDAVAdapter);
102 }
103
104
105
106
107
108
109 public ResourceAdapter getWebDAVResourceAdapter() {
110 return adapter;
111 }
112
113
114
115
116
117
118 public void setWebDAVResourceAdapter(ResourceAdapter webDAVAdapter) {
119 this.adapter = webDAVAdapter;
120 }
121
122
123
124
125
126 public CollectionHTMLRenderer getCollectionHTMLRenderer() {
127 return collectionRenderer;
128 }
129
130
131
132
133
134 public void setCollectionHTMLRenterer(CollectionHTMLRenderer collectionHTMLRenderer) {
135 this.collectionRenderer = collectionHTMLRenderer;
136 }
137
138
139
140
141
142 public boolean isReadOnly() {
143 return readOnly;
144 }
145
146
147
148
149
150 public void setReadOnly(boolean readOnly) {
151 this.readOnly = readOnly;
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165 protected Object findResource(HTTPConnection httpConnection) {
166 return adapter.findResource(httpConnection.getComponentResourcePath());
167 }
168
169
170
171
172
173
174
175 @Override
176 protected void cacheMethods() {
177 super.cacheMethods();
178 if (adapter.getLockingMechanism() == null) {
179 cachedMethods.remove("LOCK");
180 cachedMethods.remove("UNLOCK");
181 }
182 }
183
184
185
186
187
188 @Override
189 public void methodOPTIONS(HTTPConnection httpConnection) {
190 super.methodOPTIONS(httpConnection);
191 httpConnection.getResponseHeaders().putOnly("DAV", "1,2");
192 }
193
194
195
196
197
198
199 public void methodGET(HTTPConnection httpConnection) {
200 Object resource = findResource(httpConnection);
201 if (adapter.exists(resource)) {
202 Ranges ranges = collectRange(httpConnection);
203 if (adapter.isCollection(resource)) {
204 if (ranges != null) {
205 httpConnection.setResponseStatus(Status.UNSUPPORTED_MEDIA_TYPE);
206 } else {
207 collectionRenderer.render(httpConnection, adapter, resource);
208 }
209 } else {
210 transmitResource(httpConnection, resource, httpConnection, ranges);
211 }
212 } else {
213 httpConnection.setResponseStatus(Status.NOT_FOUND);
214 }
215 }
216
217
218
219
220
221
222
223
224
225 protected void transmitResource(HTTPConnection httpConnection, Object resource, Adaptable output, Ranges ranges) {
226 long size = adapter.resourceLength(resource);
227 if ((ranges != null) && (size >= 0)) {
228 ranges.setSize(size);
229 }
230
231 InputStream in = null;
232
233 if (ranges == null) {
234 try {
235 in = adapter.getInputStream(resource);
236 } catch (IOException ignore) {
237 httpConnection.setResponseStatus(Status.FORBIDDEN);
238 return;
239 }
240 } else if (!ranges.isMultiRange()) {
241 long from = ranges.getSingleRange().getFrom();
242 long to = ranges.getSingleRange().getTo();
243
244 if ((from < 0) || (to >= size)) {
245 httpConnection.setResponseStatus(Status.RANGE_NOT_SATISFIABLE);
246 } else {
247 size = to - from + 1;
248 try {
249 in = adapter.getInpusStream(resource, from, size);
250 } catch (IOException e) {
251 httpConnection.setResponseStatus(Status.FORBIDDEN);
252 return;
253 }
254 }
255 } else {
256
257 httpConnection.setResponseStatus(Status.UNSUPPORTED_MEDIA_TYPE);
258 return;
259 }
260
261 if (in != null) {
262 try {
263 boolean oldLoggingState = false;
264 LoggingConnection loggingConnection = (LoggingConnection)httpConnection.adapt(LoggingConnection.class);
265 if (loggingConnection != null) {
266 oldLoggingState = loggingConnection.isLogging();
267 loggingConnection.setLogging(false);
268 }
269 try {
270 OutputStream out = (OutputStream)output.adapt(OutputStream.class);
271
272 int bufSize = bufferSize;
273 if ((size > 0) && (bufSize > size)) {
274 bufSize = (int)size;
275 }
276 byte[] buffer = new byte[bufSize];
277 boolean ok = (size != 0);
278
279 while (ok) {
280 int r = bufSize;
281 if ((size > 0) && (r > size)) {
282 r = (int)size;
283 }
284 r = in.read(buffer, 0, r);
285 if (r <= 0) {
286 ok = false;
287 } else {
288 out.write(buffer, 0, r);
289 if (size >= 0) {
290 size = size - r;
291 if (size <= 0) {
292 ok = false;
293 }
294 }
295 }
296 }
297 } finally {
298 if (loggingConnection != null) {
299 loggingConnection.setLogging(oldLoggingState);
300 }
301 in.close();
302 }
303 } catch (IOException e) {
304 throw new RuntimeIOException(e);
305 }
306 if (ranges != null) {
307 httpConnection.getResponseHeaders().putOnly("Content-Range", ranges.format());
308 }
309 }
310 }
311
312
313
314
315
316
317 public void methodHEAD(HTTPConnection httpConnection) {
318 Object resource = findResource(httpConnection);
319 if (adapter.exists(resource)) {
320 Ranges ranges = collectRange(httpConnection);
321 long size = adapter.resourceLength(resource);
322 if (ranges != null) {
323 ranges.setSize(size);
324
325 httpConnection.getResponseHeaders().putOnly("Content-Range", ranges.format());
326 } else {
327 httpConnection.getResponseHeaders().putOnly("Content-Length", Long.toString(size));
328 }
329 } else {
330 httpConnection.setResponseStatus(Status.NOT_FOUND);
331 }
332 }
333
334
335
336
337
338
339 public void methodPUT(HTTPConnection httpConnection) {
340 if (readOnly) {
341 httpConnection.setResponseStatus(Status.FORBIDDEN);
342 return;
343 }
344
345 Object resource = findResource(httpConnection);
346 Object parentResource = adapter.findParentResource(resource);
347
348 boolean oldFile = adapter.exists(resource);
349 if (oldFile && adapter.isCollection(resource)) {
350 httpConnection.setResponseStatus(Status.CONFLICT);
351 return;
352 } else if ((parentResource != null) && !adapter.exists(parentResource)) {
353 httpConnection.setResponseStatus(Status.CONFLICT);
354 return;
355 }
356
357 boolean resourceLocked = false;
358 boolean parentLocked = false;
359 IF lockDetails = null;
360 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
361 if (lockingMechanism != null) {
362 lockDetails = new IF();
363 resourceLocked = lockingMechanism.isLocked(resource);
364 if (parentResource != null) {
365 parentLocked = lockingMechanism.isLocked(parentResource);
366 }
367
368 boolean ok;
369 if (parentLocked) {
370 ok = lockDetails.parse(httpConnection, adapter, resource, parentResource);
371 } else {
372 ok = lockDetails.parse(httpConnection, adapter, resource, null);
373 }
374 if (!ok) {
375 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
376 return;
377 }
378
379
380
381
382
383
384 if ((lockDetails.token == null) && resourceLocked) {
385
386
387
388
389
390 if ((lockDetails.parentToken == null) || !lockingMechanism.isAccessAllowed(resource, lockDetails.parentToken)) {
391 httpConnection.setResponseStatus(STATUS_LOCKED);
392 return;
393 }
394 } else if ((lockDetails.token != null) && !resourceLocked) {
395 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
396 return;
397 }
398 }
399
400 String contentRangeHeader = httpConnection.getRequestHeaders().getOnly("Content-Range");
401 Ranges ranges = null;
402 if (contentRangeHeader != null) {
403 ranges = Ranges.parseContentRange(contentRangeHeader);
404 }
405
406 OutputStream out = null;
407 if (ranges == null) {
408 try {
409 out = adapter.getOutputStream(resource);
410 } catch (IOException e) {
411 httpConnection.setResponseStatus(Status.FORBIDDEN);
412 return;
413 }
414 if (!resourceLocked && parentLocked) {
415 Lock lock = lockingMechanism.findLock(lockDetails.parentToken);
416 lockingMechanism.lockResource(lock, resource);
417 }
418 } else if (!ranges.isMultiRange()) {
419 if (ranges.getSize() >= 0) {
420
421 long from = ranges.getSingleRange().getFrom();
422 long to = ranges.getSingleRange().getTo();
423 long size = ranges.getSize();
424 if ((from < 0) || (to >= size)) {
425 httpConnection.setResponseStatus(Status.RANGE_NOT_SATISFIABLE);
426 } else {
427 try {
428 out = adapter.getOutputStream(resource, from, to - from);
429 } catch (IOException e) {
430 httpConnection.setResponseStatus(Status.FORBIDDEN);
431 return;
432 }
433 if (!resourceLocked && parentLocked) {
434 Lock lock = lockingMechanism.findLock(lockDetails.parentToken);
435 lockingMechanism.lockResource(lock, resource);
436 }
437 }
438 } else {
439 httpConnection.setResponseStatus(Status.NOT_IMPLEMENTED);
440 return;
441 }
442 } else {
443
444 httpConnection.setResponseStatus(Status.NOT_IMPLEMENTED);
445 return;
446 }
447
448 if (out != null) {
449 try {
450 boolean oldLoggingState = false;
451 LoggingConnection loggingConnection = (LoggingConnection)httpConnection.adapt(LoggingConnection.class);
452 if (loggingConnection != null) {
453 oldLoggingState = loggingConnection.isLogging();
454 loggingConnection.setLogging(false);
455 }
456 try {
457 InputStream in = (InputStream)httpConnection.adapt(InputStream.class);
458
459 int bufSize = bufferSize;
460
461
462
463 byte[] buffer = new byte[bufSize];
464 int r = 0;
465 while (r >= 0) {
466 r = bufSize;
467
468 r = in.read(buffer, 0, r);
469 if (r > 0) {
470 out.write(buffer, 0, r);
471 }
472 }
473 } finally {
474 if (loggingConnection != null) {
475 loggingConnection.setLogging(oldLoggingState);
476 }
477 out.close();
478 }
479 } catch (IOException e) {
480 throw new RuntimeIOException(e);
481 }
482 if (oldFile) {
483 httpConnection.setResponseStatus(Status.NO_CONTENT);
484 } else {
485 httpConnection.setResponseStatus(Status.CREATED);
486 }
487 }
488 }
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506 public void methodDELETE(HTTPConnection httpConnection) {
507 if (readOnly) {
508 httpConnection.setResponseStatus(Status.FORBIDDEN);
509 return;
510 }
511
512 Object resource = findResource(httpConnection);
513 Object parentResource = adapter.findParentResource(resource);
514
515 int depth = Depth.collectDepth(httpConnection);
516 if ((depth != Depth.INFINITY) && (depth != Depth.NONE)) {
517
518 httpConnection.setResponseStatus(Status.BAD_REQUEST);
519 return;
520 }
521
522 if (!adapter.exists(resource)) {
523 httpConnection.setResponseStatus(Status.NOT_FOUND);
524 return;
525 }
526
527 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
528
529 boolean resourceLocked = false;
530 boolean parentLocked = false;
531 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
532 if (lockingMechanism != null) {
533 IF lockDetails = new IF();
534 resourceLocked = lockingMechanism.isLocked(resource);
535 if (parentResource != null) {
536 parentLocked = lockingMechanism.isLocked(parentResource);
537 }
538 boolean ok;
539 if (parentLocked) {
540 ok = lockDetails.parse(httpConnection, adapter, resource, parentResource);
541 } else {
542 ok = lockDetails.parse(httpConnection, adapter, resource, null);
543 }
544 if (!ok) {
545 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
546 return;
547 }
548
549 if ((lockDetails.token == null) && resourceLocked) {
550 httpConnection.setResponseStatus(STATUS_LOCKED);
551 return;
552 } else if ((lockDetails.token != null) && !resourceLocked) {
553 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
554 return;
555 } else if ((lockDetails.token != null) && adapter.isCollection(resource)) {
556 if (isLockedRecursive(lockingMechanism, lockDetails, multiStatus, httpConnection, resource, adapter.getResourceName(resource))) {
557 multiStatus.render();
558 }
559 }
560 }
561
562 if (deleteRecursive(multiStatus, "/", resource)) {
563 httpConnection.setResponseStatus(Status.NO_CONTENT);
564 } else {
565 multiStatus.render();
566 }
567 }
568
569
570
571
572
573
574
575
576
577 protected boolean deleteRecursive(MultiStatus multiStatus, String path, Object resource) {
578 boolean ok = true;
579 if (adapter.isCollection(resource)) {
580 String p = IOUtils.addPaths(path, adapter.getResourceName(resource));
581 Object[] resources = adapter.collectionElements(resource);
582 for (Object r : resources) {
583 ok = ok && deleteRecursive(multiStatus, p, r);
584 }
585 }
586 ok = ok && deleteLeafImpl(multiStatus, path, resource);
587 return ok;
588 }
589
590
591
592
593
594
595
596
597
598 protected boolean deleteLeafImpl(MultiStatus multiStatus, String path, Object resource) {
599 Response response = multiStatus.newResponse(path);
600 try {
601 adapter.delete(resource);
602 response.setStatus(Status.OK);
603 return true;
604 } catch (IOException e) {
605 response.setResponseDescription(e.getMessage());
606 response.setStatus(Status.FORBIDDEN);
607 return false;
608 }
609 }
610
611
612
613
614
615
616
617 public void methodPROPFIND(HTTPConnection httpConnection) {
618 Object resource = findResource(httpConnection);
619 if (adapter.exists(resource)) {
620 int depth = Depth.collectDepth(httpConnection);
621 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
622 PropFind propFind;
623 try {
624 propFind = (PropFind)readRequestXML(httpConnection, PropFind.class);
625 } catch (SAXException e) {
626 httpConnection.setResponseStatus(Status.BAD_REQUEST);
627 return;
628 }
629
630 if (propFind == null) {
631
632 propFind = new PropFind(null, null);
633 propFind.setAllprop(true);
634 }
635
636 if (adapter.exists(resource)) {
637 Response response = multiStatus.newResponse();
638 obtainProps(response, resource, propFind);
639 if ((depth != Depth.ZERO) && adapter.isCollection(resource)) {
640 Object[] resources = adapter.collectionElements(resource);
641 if (resources != null) {
642 for (int i = 0; i < resources.length; i++) {
643 if (depth == Depth.INFINITY) {
644 String path = adapter.getResourceName(resources[i]);
645 obtainPropsRecursive(multiStatus, resource, propFind, path);
646 } else {
647 response = multiStatus.newResponse(adapter.getResourceName(resources[i]));
648 obtainProps(response, resources[i], propFind);
649 }
650 }
651 }
652 }
653 } else {
654 multiStatus.addSimpleResponse(Status.NOT_FOUND);
655 }
656 fixUnknownPropsResponse(multiStatus);
657 multiStatus.render(true);
658 } else {
659 httpConnection.setResponseStatus(Status.NOT_FOUND);
660 }
661 }
662
663
664
665
666
667
668
669
670
671 protected void obtainPropsRecursive(MultiStatus multiStatus, Object resource, PropFind propFind, String path) {
672 Response response = multiStatus.newResponse(path);
673 obtainProps(response, resource, propFind);
674 if (adapter.isCollection(resource)) {
675 Object[] resources = adapter.collectionElements(resource);
676 if (resources != null) {
677 for (int i = 0; i < resources.length; i++) {
678 String p = IOUtils.addPaths(path, adapter.getResourceName(resources[i]));
679 obtainPropsRecursive(multiStatus, resource, propFind, p);
680 }
681 }
682 }
683 }
684
685
686
687
688
689
690
691 protected void obtainProps(Response response, Object resource, PropFind propFind) {
692
693 if (propFind.isPropname()) {
694 Propstat propStat = new Propstat(response);
695 propStat.setStatus(Status.OK);
696 response.getPropStats().add(propStat);
697 ResponseProperty[] properties = adapter.getDefaultResponseProperties(resource);
698 for (ResponseProperty property : properties) {
699 propStat.getProp().getProperties().add(property);
700 }
701 } else {
702 Propstat positive = null;
703 Map<String, Propstat> responses = null;
704
705 List<RequestProperty> properties = null;
706 if (propFind.isAllprop()) {
707 properties = Arrays.asList(adapter.getDefaultRequestProperties(resource));
708 } else {
709 RequestProp prop = propFind.getProp();
710 properties = prop.getProperties();
711 }
712
713
714
715 for (RequestProperty property : properties) {
716 ResponseProperty responseProperty = property.processResponse(adapter, resource);
717 Status status = responseProperty.getStatus();
718 if (status == Status.OK) {
719 if (positive == null) {
720 positive = new Propstat(response);
721 positive.setStatus(Status.OK);
722 }
723 positive.getProp().getProperties().add(responseProperty);
724 } else {
725 if (responses == null) {
726 responses = new HashMap<String, Propstat>();
727 }
728 Propstat propstat = responses.get(status.getCode());
729 if (propstat == null) {
730 propstat = new Propstat(response);
731 propstat.setStatus(responseProperty.getStatus());
732 responses.put(propstat.getStatus().getCode(), propstat);
733 }
734 propstat.getProp().getProperties().add(responseProperty);
735 }
736 }
737 if (responses != null) {
738 if (positive != null) {
739 response.getPropStats().add(positive);
740 }
741 response.getPropStats().addAll(responses.values());
742 } else {
743 if (positive != null) {
744 response.getPropStats().add(positive);
745 }
746 }
747 }
748 }
749
750
751
752
753
754
755
756 public void methodPROPPATCH(HTTPConnection httpConnection) {
757 if (readOnly) {
758 httpConnection.setResponseStatus(Status.FORBIDDEN);
759 return;
760 }
761
762 Object resource = findResource(httpConnection);
763 int depth = Depth.collectDepth(httpConnection);
764
765 PropertyUpdate propertyUpdate;
766 try {
767 propertyUpdate = (PropertyUpdate)readRequestXML(httpConnection, PropertyUpdate.class);
768 } catch (SAXException e) {
769 httpConnection.setResponseStatus(Status.BAD_REQUEST);
770 return;
771 }
772 if (propertyUpdate == null) {
773 httpConnection.setResponseStatus(Status.BAD_REQUEST);
774 return;
775 }
776 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
777 if (lockingMechanism != null) {
778 IF lockDetails = new IF();
779 boolean resourceLocked = lockingMechanism.isLocked(resource);
780 if (!lockDetails.parse(httpConnection, adapter, resource, null)) {
781 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
782 return;
783 }
784
785 if ((lockDetails.token == null) && resourceLocked) {
786 httpConnection.setResponseStatus(STATUS_LOCKED);
787 return;
788 } else if ((lockDetails.token != null) && !resourceLocked) {
789 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
790 return;
791 } else if ((lockDetails.token != null) && adapter.isCollection(resource)) {
792 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
793 if (isLockedRecursive(lockingMechanism, lockDetails, multiStatus, httpConnection, resource, adapter.getResourceName(resource))) {
794 multiStatus.render(true);
795 }
796 }
797 }
798
799 if (adapter.exists(resource)) {
800 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
801 updateProps(multiStatus, resource, depth, propertyUpdate);
802 fixUnknownPropsResponse(multiStatus);
803 multiStatus.render();
804 } else {
805 httpConnection.setResponseStatus(Status.NOT_FOUND);
806 }
807 }
808
809
810
811
812
813
814
815
816
817 protected void updateProps(MultiStatus multiStatus, Object resource, int depth, PropertyUpdate propertyUpdate) {
818 Response response = multiStatus.newResponse();
819 updateProps(response, resource, propertyUpdate);
820 if ((depth != Depth.ZERO) && adapter.isCollection(resource)) {
821 Object[] resources = adapter.collectionElements(resource);
822 if (resources != null) {
823 for (int i = 0; i < resources.length; i++) {
824 if (depth == Depth.INFINITY) {
825 String path = adapter.getResourceName(resources[i]);
826 updatePropsRecursive(multiStatus, resource, propertyUpdate, path);
827 } else {
828 response = multiStatus.newResponse(adapter.getResourceName(resources[i]));
829 updateProps(response, resources[i], propertyUpdate);
830 }
831 }
832 }
833 }
834 }
835
836
837
838
839
840
841
842
843
844 protected void updatePropsRecursive(MultiStatus multiStatus, Object resource, PropertyUpdate propertyUpdate, String path) {
845 Response response = multiStatus.newResponse(path);
846
847 updateProps(response, resource, propertyUpdate);
848 if (adapter.isCollection(resource)) {
849 Object[] resources = adapter.collectionElements(resource);
850 if (resources != null) {
851 for (int i = 0; i < resources.length; i++) {
852 String p = IOUtils.addPaths(path, adapter.getResourceName(resources[i]));
853 updatePropsRecursive(multiStatus, resource, propertyUpdate, p);
854 }
855 }
856 }
857 }
858
859
860
861
862
863
864
865
866 protected void updateProps(Response response, Object resource, PropertyUpdate propertyUpdate) {
867 Propstat positive = null;
868 Map<String, Propstat> responses = null;
869 for (RequestProp prop : propertyUpdate.getProperties()) {
870
871 for (RequestProperty property : prop.getProperties()) {
872 ResponseProperty responseProperty = null;
873 if (prop.getType() == RequestProp.SET) {
874 responseProperty = property.processSetProperty(adapter, resource);
875 } else {
876 responseProperty = property.processRemoveProperty(adapter, resource);
877 }
878 Status status = responseProperty.getStatus();
879 if (status == Status.OK) {
880 if (positive == null) {
881 positive = new Propstat(response);
882 positive.setStatus(Status.OK);
883 }
884 positive.getProp().getProperties().add(responseProperty);
885 } else {
886 if (responses == null) {
887 responses = new HashMap<String, Propstat>();
888 }
889 Propstat propstat = responses.get(status.getCode());
890 if (propstat == null) {
891 propstat = new Propstat(response);
892 propstat.setStatus(responseProperty.getStatus());
893 responses.put(propstat.getStatus().getCode(), propstat);
894 }
895 propstat.getProp().getProperties().add(responseProperty);
896 }
897 }
898 }
899 if (responses != null) {
900 if (positive != null) {
901 response.getPropStats().add(positive);
902 }
903 response.getPropStats().addAll(responses.values());
904 } else {
905 if (positive != null) {
906 response.getPropStats().add(positive);
907 }
908 }
909 }
910
911
912
913
914
915 protected void fixUnknownPropsResponse(MultiStatus multiStatus) {
916 if ((multiStatus.getResponses().size() == 1) && (multiStatus.getResponses().get(0).getPropStats().size() == 0)) {
917 Propstat propStat = new Propstat(multiStatus.getResponses().get(0));
918 propStat.setStatus(Status.NOT_IMPLEMENTED);
919 multiStatus.getResponses().get(0).getPropStats().add(propStat);
920 }
921 }
922
923
924
925
926
927
928
929 public void methodMKCOL(HTTPConnection httpConnection) {
930 if (readOnly) {
931 httpConnection.setResponseStatus(Status.FORBIDDEN);
932 return;
933 }
934
935 Object resource = findResource(httpConnection);
936 Object parentResource = adapter.findParentResource(resource);
937 if ((parentResource != null) && !adapter.exists(parentResource)) {
938 httpConnection.setResponseStatus(Status.CONFLICT);
939 return;
940 }
941
942 if (adapter.exists(resource)) {
943 httpConnection.setResponseStatus(Status.METHOD_NOT_ALLOWED);
944 return;
945 }
946
947 boolean resourceLocked = false;
948 boolean parentLocked = false;
949 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
950 if (lockingMechanism != null) {
951 IF lockDetails = new IF();
952 resourceLocked = lockingMechanism.isLocked(resource);
953 if (parentResource != null) {
954 parentLocked = lockingMechanism.isLocked(parentResource);
955 }
956
957 boolean ok;
958 if (parentLocked) {
959 ok = lockDetails.parse(httpConnection, adapter, resource, parentResource);
960 } else {
961 ok = lockDetails.parse(httpConnection, adapter, resource, null);
962 }
963 if (!ok) {
964 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
965 return;
966 }
967
968 if ((lockDetails.token == null) && resourceLocked) {
969 httpConnection.setResponseStatus(STATUS_LOCKED);
970 return;
971 } else if ((lockDetails.token != null) && !resourceLocked) {
972 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
973 return;
974 }
975 }
976
977 InputStream in = (InputStream)httpConnection.adapt(InputStream.class);
978 try {
979 int r = in.read();
980 if (r != -1) {
981 httpConnection.setResponseStatus(Status.UNSUPPORTED_MEDIA_TYPE);
982 return;
983 }
984 } catch (IOException ignore) {
985 }
986
987 try {
988 adapter.makeCollection(resource);
989 httpConnection.setResponseStatus(Status.CREATED);
990 } catch (IOException e) {
991
992 httpConnection.setResponseStatus(Status.FORBIDDEN);
993 }
994 }
995
996
997
998
999
1000
1001 public void methodCOPY(HTTPConnection httpConnection) {
1002 if (readOnly) {
1003 httpConnection.setResponseStatus(Status.FORBIDDEN);
1004 return;
1005 }
1006
1007 int depth = Depth.collectDepth(httpConnection);
1008 if (depth == Depth.NONE) {
1009 depth = Depth.INFINITY;
1010 }
1011
1012
1013 } catch (SAXException e) {
1014 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1015 return;
1016 }
1017
1018 if (depth == Depth.ONE) {
1019
1020 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1021 return;
1022 }
1023
1024 Object fromResource = findResource(httpConnection);
1025
1026 boolean overwrite = !"F".equals(httpConnection.getRequestHeaders().getOnly("Overwrite"));
1027 String destHeader = httpConnection.getRequestHeaders().getOnly("Destination");
1028 Object destResource = URIUtils.uriToResource(httpConnection, adapter, destHeader);
1029 if (destResource == null) {
1030 httpConnection.setResponseStatus(Status.FORBIDDEN);
1031 return;
1032 }
1033
1034 if (adapter.exists(destResource) && !overwrite) {
1035 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1036 return;
1037 }
1038
1039 Object destParentResource = adapter.findParentResource(destResource);
1040 if ((destParentResource != null) && !adapter.exists(destParentResource)) {
1041 httpConnection.setResponseStatus(Status.CONFLICT);
1042 return;
1043 }
1044
1045 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
1046 boolean destLocked = false;
1047 boolean destParentLocked = false;
1048 IF lockDetails = null;
1049
1050 if (lockingMechanism != null) {
1051 lockDetails = new IF();
1052 destLocked = lockingMechanism.isLocked(destResource);
1053 if (destParentResource != null) {
1054 destParentLocked = lockingMechanism.isLocked(destParentResource);
1055 }
1056
1057 boolean ok;
1058 if (destParentLocked) {
1059 ok = lockDetails.parse(httpConnection, adapter, destResource, destParentResource);
1060 } else {
1061 ok = lockDetails.parse(httpConnection, adapter, destResource, null);
1062 }
1063 if (!ok) {
1064 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1065 return;
1066 }
1067
1068 if ((lockDetails.token == null) && destLocked) {
1069 httpConnection.setResponseStatus(STATUS_LOCKED);
1070 return;
1071 } else if ((lockDetails.token != null) && !destLocked) {
1072 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1073 return;
1074 } else if ((lockDetails.token != null) && adapter.isCollection(destResource)) {
1075
1076 }
1077 }
1078
1079 boolean newFile = true;
1080 if (overwrite && adapter.exists(destResource)) {
1081 newFile = false;
1082 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
1083 if (!deleteRecursive(multiStatus, "/", destResource)) {
1084 multiStatus.render();
1085 return;
1086 }
1087 }
1088
1089 try {
1090 adapter.copy(fromResource, destResource, (depth == Depth.INFINITY));
1091 if (newFile) {
1092 if (destParentLocked) {
1093 Lock lock = lockingMechanism.findLock(lockDetails.token);
1094 lockingMechanism.lockResource(lock, destResource);
1095 }
1096 httpConnection.setResponseStatus(Status.CREATED);
1097 } else {
1098 httpConnection.setResponseStatus(Status.NO_CONTENT);
1099 }
1100 } catch (IOException e) {
1101 httpConnection.setResponseStatus(Status.FORBIDDEN);
1102 }
1103
1104 }
1105
1106
1107
1108
1109
1110
1111
1112 public void methodMOVE(HTTPConnection httpConnection) {
1113 if (readOnly) {
1114 httpConnection.setResponseStatus(Status.FORBIDDEN);
1115 return;
1116 }
1117
1118 int depth = Depth.collectDepth(httpConnection);
1119 if (depth == Depth.NONE) {
1120 depth = Depth.INFINITY;
1121 }
1122
1123 readRequestXML(httpConnection, PropertyBehavior.class);
1124 } catch (SAXException e) {
1125 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1126 return;
1127 }
1128
1129 if (depth != Depth.INFINITY) {
1130
1131 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1132 return;
1133 }
1134
1135 Object fromResource = findResource(httpConnection);
1136
1137 boolean overwrite = !"F".equals(httpConnection.getRequestHeaders().getOnly("Overwrite"));
1138 String destHeader = httpConnection.getRequestHeaders().getOnly("Destination");
1139 Object destResource = URIUtils.uriToResource(httpConnection, adapter, destHeader);
1140
1141 if (destResource == null) {
1142 httpConnection.setResponseStatus(Status.FORBIDDEN);
1143 return;
1144 }
1145
1146 if (adapter.exists(destResource) && !overwrite) {
1147 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1148 return;
1149 }
1150
1151 Object destParentResource = adapter.findParentResource(destResource);
1152 if ((destParentResource != null) && !adapter.exists(destParentResource)) {
1153 httpConnection.setResponseStatus(Status.CONFLICT);
1154 return;
1155 }
1156
1157 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
1158 boolean destLocked = false;
1159 boolean destParentLocked = false;
1160 IF lockDetails = null;
1161
1162 if (lockingMechanism != null) {
1163 lockDetails = new IF();
1164 Object fromParentResource = adapter.findParentResource(fromResource);
1165 boolean fromLocked = lockingMechanism.isLocked(fromResource);
1166 boolean fromParentLocked = false;
1167 if (fromParentResource != null) {
1168 fromParentLocked = lockingMechanism.isLocked(fromParentResource);
1169 }
1170
1171 boolean ok;
1172 if (fromParentLocked) {
1173 ok = lockDetails.parse(httpConnection, adapter, fromResource, fromParentResource);
1174 } else {
1175 ok = lockDetails.parse(httpConnection, adapter, fromResource, null);
1176 }
1177 if (!ok) {
1178 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1179 return;
1180 }
1181
1182 if ((lockDetails.token == null) && fromLocked) {
1183 httpConnection.setResponseStatus(STATUS_LOCKED);
1184 return;
1185 } else if ((lockDetails.token != null) && !fromLocked) {
1186 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1187 return;
1188 } else if ((lockDetails.token != null) && adapter.isCollection(fromResource)) {
1189 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
1190 if (isLockedRecursive(lockingMechanism, lockDetails, multiStatus, httpConnection, fromResource, adapter.getResourceName(fromResource))) {
1191 multiStatus.render();
1192 return;
1193 }
1194 }
1195
1196
1197 destLocked = lockingMechanism.isLocked(destResource);
1198 if (destLocked) {
1199 if ((lockDetails.clearedResources == null) || !lockDetails.clearedResources.contains(destResource)) {
1200 if (!lockingMechanism.isAccessAllowed(destResource, lockDetails.token)) {
1201 httpConnection.setResponseStatus(STATUS_LOCKED);
1202 return;
1203 }
1204 }
1205 }
1206
1207 if (destParentResource != null) {
1208 destParentLocked = lockingMechanism.isLocked(destParentResource);
1209 }
1210 if (destParentLocked) {
1211 if ((lockDetails.clearedResources == null) || !lockDetails.clearedResources.contains(destParentResource)) {
1212 if (!lockingMechanism.isAccessAllowed(destParentResource, lockDetails.token)) {
1213 httpConnection.setResponseStatus(STATUS_LOCKED);
1214 return;
1215 }
1216 }
1217 }
1218 }
1219
1220 boolean newFile = true;
1221 if (overwrite && !fromResource.equals(destResource) && adapter.exists(destResource)) {
1222 newFile = false;
1223 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
1224 if (!deleteRecursive(multiStatus, "/", destResource)) {
1225 multiStatus.render();
1226 return;
1227 }
1228 }
1229
1230 try {
1231 adapter.move(fromResource, destResource);
1232 if (newFile) {
1233 if (destParentLocked) {
1234 Lock lock = lockingMechanism.findLock(lockDetails.token);
1235 lockingMechanism.lockResource(lock, destResource);
1236 }
1237 httpConnection.setResponseStatus(Status.CREATED);
1238 } else {
1239 httpConnection.setResponseStatus(Status.NO_CONTENT);
1240 }
1241 if ((lockingMechanism != null) && lockingMechanism.isLocked(fromResource)) {
1242 lockingMechanism.removeLocks(fromResource);
1243 }
1244 } catch (IOException e) {
1245 httpConnection.setResponseStatus(Status.FORBIDDEN);
1246 }
1247 }
1248
1249
1250
1251
1252
1253
1254
1255 public void methodLOCK(HTTPConnection httpConnection) {
1256 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
1257 Object resource = findResource(httpConnection);
1258
1259 LockInfo lockInfo;
1260 try {
1261 lockInfo = (LockInfo)readRequestXML(httpConnection, LockInfo.class);
1262 } catch (SAXException e) {
1263 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1264 return;
1265 }
1266 if (lockingMechanism == null) {
1267 httpConnection.setResponseStatus(Status.METHOD_NOT_ALLOWED);
1268 return;
1269 }
1270
1271 int depth = Depth.collectDepth(httpConnection);
1272 if (depth == Depth.NONE) {
1273 depth = Depth.INFINITY;
1274 }
1275 if ((depth == Depth.ONE)
1276 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1277 } else {
1278 Lock[] locks = null;
1279 IF lockDetails = new IF();
1280
1281 if (!lockDetails.parse(httpConnection, adapter, resource, null)) {
1282 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1283 return;
1284 }
1285
1286 if (lockingMechanism.isLocked(resource)) {
1287 if (lockInfo != null) {
1288 locks = lockingMechanism.getLocks(resource);
1289 for (Lock lock : locks) {
1290 if (lock.getScope() == LockingMechanism.SCOPE_EXCLUSIVE) {
1291 httpConnection.setResponseStatus(STATUS_LOCKED);
1292 return;
1293 }
1294 }
1295 }
1296 } else {
1297 if (lockInfo == null) {
1298 httpConnection.setResponseStatus(Status.PRECONDITION_FAILED);
1299 return;
1300 }
1301 }
1302
1303 if (adapter.exists(resource)) {
1304 Timeout[] timeouts = collectTimeouts(httpConnection);
1305 MultiStatus multiStatus = new MultiStatus(adapter.getNamespacesProvider(), httpConnection);
1306
1307 Lock lock = null;
1308 if (lockInfo != null) {
1309
1310
1311
1312
1313
1314
1315
1316 Object owner = lockInfo.getOwner();
1317 if (timeouts == null) {
1318 lock = lockingMechanism.createLock(lockInfo.getType(), lockInfo.getScope(), owner, null, depth);
1319 } else if (timeouts.length == 1) {
1320 lock = lockingMechanism.createLock(lockInfo.getType(), lockInfo.getScope(), owner, timeouts[0], depth);
1321 } else {
1322 int i = 0;
1323 while ((lock == null) && (i < timeouts.length)) {
1324 lock = lockingMechanism.createLock(lockInfo.getType(), lockInfo.getScope(), owner, timeouts[i], depth);
1325 i++;
1326 }
1327 }
1328 Response response = multiStatus.newResponse();
1329 boolean ok = true;
1330 if (lockImpl(response, lock, lockingMechanism, lockInfo, owner, depth == Depth.INFINITY, resource)) {
1331 if ((depth != Depth.ZERO) && adapter.isCollection(resource)) {
1332 Object[] resources = adapter.collectionElements(resource);
1333 if (resources != null) {
1334 int i = 0;
1335 while (ok && (i < resources.length)) {
1336 String path = adapter.getResourceName(resources[i]);
1337 ok = lockRecursive(multiStatus, lock, lockingMechanism, lockInfo, owner, resources[i], path);
1338 i ++;
1339 }
1340 }
1341 }
1342 } else {
1343 ok = false;
1344 }
1345 if (ok) {
1346 httpConnection.getResponseHeaders().putOnly("Lock-Token", lock.getToken().toString());
1347 } else {
1348 lockingMechanism.unlockResources(lock);
1349 }
1350 multiStatus.render(false);
1351 } else {
1352
1353 if (lockDetails.token != null) {
1354 lock = lockingMechanism.findLock(lockDetails.token);
1355 if ((timeouts == null) || (timeouts.length == 0)) {
1356 lock.refreshTimeout(null);
1357 } else {
1358 boolean ok = false;
1359 int i = 0;
1360 while (!ok) {
1361 ok = lock.refreshTimeout(timeouts[i]);
1362 i++;
1363 }
1364 }
1365 httpConnection.getResponseHeaders().putOnly("Timeout", lock.getTimeout().asString());
1366 Response response = multiStatus.newResponse();
1367 Propstat propstat = new Propstat(response);
1368 propstat.setStatus(Status.OK);
1369 LockDiscovery lockDiscovery = new LockDiscovery(Status.OK);
1370 lockDiscovery.getLocks().add(lock);
1371 propstat.getProp().getProperties().add(lockDiscovery);
1372 response.getPropStats().add(propstat);
1373 multiStatus.render(false);
1374 } else {
1375 httpConnection.setResponseStatus(Status.CONFLICT);
1376 }
1377 }
1378 } else {
1379 httpConnection.setResponseStatus(Status.NOT_FOUND);
1380 }
1381 }
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 protected boolean lockRecursive(MultiStatus multiStatus, Lock lock, LockingMechanism lockingMechanism, LockInfo lockInfo, Object owner, Object resource, String path) {
1397 Response response = multiStatus.newResponse(path);
1398 if (lockImpl(response, lock, lockingMechanism, lockInfo, owner, true, resource)) {
1399 if (adapter.isCollection(resource)) {
1400 Object[] resources = adapter.collectionElements(resource);
1401 if (resources != null) {
1402 for (int i = 0; i < resources.length; i++) {
1403 String p = IOUtils.addPaths(path, adapter.getResourceName(resources[i]));
1404 if (!lockRecursive(multiStatus, lock, lockingMechanism, lockInfo, owner, resource, p)) {
1405 return false;
1406 }
1407 }
1408 }
1409 }
1410 return true;
1411 } else {
1412 return false;
1413 }
1414 }
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 protected boolean lockImpl(Response response, Lock lock, LockingMechanism lockingMechanism, LockInfo lockInfo, Object owner, boolean recursive, Object resource) {
1429
1430 Lock[] locks = lockingMechanism.getLocks(resource);
1431 if (locks != null) {
1432 if ((lockInfo.getScope() == LockingMechanism.SCOPE_EXCLUSIVE)) {
1433 response.setStatus(STATUS_LOCKED);
1434 return false;
1435 } else {
1436 for (Lock l : locks) {
1437 if (l.getScope() == LockingMechanism.SCOPE_EXCLUSIVE) {
1438 response.setStatus(STATUS_LOCKED);
1439 return false;
1440 }
1441 }
1442 }
1443 }
1444
1445
1446
1447
1448
1449 int[] lockScopes = lockingMechanism.getSupportedLockScopes(resource);
1450 if (lockScopes.length == 0) {
1451 response.setStatus(Status.PRECONDITION_FAILED);
1452 return false;
1453 } else {
1454 if (lockingMechanism.lockResource(lock, resource)) {
1455 Propstat propstat = new Propstat(response);
1456 LockDiscovery lockDiscovery = new LockDiscovery(Status.OK);
1457 lockDiscovery.getLocks().add(lock);
1458 propstat.getProp().getProperties().add(lockDiscovery);
1459 response.getPropStats().add(propstat);
1460 propstat.setStatus(Status.OK);
1461 return true;
1462 } else {
1463 response.setStatus(Status.PRECONDITION_FAILED);
1464 return false;
1465 }
1466 }
1467 }
1468
1469
1470
1471
1472
1473
1474 public void methodUNLOCK(HTTPConnection httpConnection) {
1475 Object resource = findResource(httpConnection);
1476 LockingMechanism lockingMechanism = adapter.getLockingMechanism();
1477 if (lockingMechanism == null) {
1478 httpConnection.setResponseStatus(Status.NO_CONTENT);
1479 return;
1480 }
1481 String token = httpConnection.getRequestHeaders().getOnly("Lock-Token");
1482 if (token != null) {
1483 if (token.startsWith("<") && token.endsWith(">") && (token.length() > 2)) {
1484 token = token.substring(1, token.length() - 1);
1485 } else {
1486 httpConnection.setResponseStatus(Status.BAD_REQUEST);
1487 return;
1488 }
1489 }
1490
1491 if (lockingMechanism.isAccessAllowed(resource, token)) {
1492 httpConnection.setResponseStatus(STATUS_LOCKED);
1493 }
1494
1495 if (adapter.exists(resource)) {
1496 Lock lock = lockingMechanism.findLock(token);
1497 if (lock != null) {
1498 lockingMechanism.unlockResources(lock);
1499 httpConnection.setResponseStatus(Status.NO_CONTENT);
1500 } else {
1501 httpConnection.setResponseStatus(STATUS_LOCKED);
1502 }
1503 } else {
1504 httpConnection.setResponseStatus(Status.NOT_FOUND);
1505 }
1506 }
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518 protected boolean isLockedRecursive(LockingMechanism lockingMechanism, IF lockDetails, MultiStatus multiStatus, HTTPConnection httpConnection, Object resource, String path) {
1519 boolean locked = false;
1520 Object[] resources = adapter.collectionElements(resource);
1521 if ((resources != null) && (resources.length > 0)) {
1522 for (Object r : resources) {
1523 String p = IOUtils.addPaths(path, adapter.getResourceName(r));
1524 if ((lockDetails.clearedResources == null) || !lockDetails.clearedResources.contains(r)) {
1525 if (!lockingMechanism.isAccessAllowed(r, lockDetails.token)) {
1526 Response response = multiStatus.newResponse(p);
1527 response.setStatus(STATUS_FAILED_DEPENDENCY);
1528 locked = true;
1529 }
1530 }
1531 if (adapter.isCollection(r)) {
1532 isLockedRecursive(lockingMechanism, lockDetails, multiStatus, httpConnection, r, p);
1533 }
1534 }
1535 }
1536
1537 return locked;
1538 }
1539
1540
1541
1542
1543
1544
1545
1546 protected Ranges collectRange(HTTPConnection connection) {
1547 String rangesHeader = connection.getRequestHeaders().getOnly("Range");
1548 if (rangesHeader != null) {
1549 Ranges ranges = Ranges.parseRange(rangesHeader);
1550 return ranges;
1551 } else {
1552 return null;
1553 }
1554 }
1555
1556
1557
1558
1559
1560
1561 protected Timeout[] collectTimeouts(HTTPConnection connection) {
1562 String timeoutHeader = connection.getRequestHeaders().getOnly("Timeout");
1563 if (timeoutHeader != null) {
1564 int i = timeoutHeader.indexOf(',');
1565 if (i >= 0) {
1566 ArrayList<Timeout> timeouts = new ArrayList<Timeout>();
1567 StringTokenizer tokenizer = new StringTokenizer(timeoutHeader, ",");
1568 while (tokenizer.hasMoreTokens()) {
1569 Timeout timeout = Timeout.parse(tokenizer.nextToken());
1570 timeouts.add(timeout);
1571 }
1572 Timeout[] res = new Timeout[timeouts.size()];
1573 return timeouts.toArray(res);
1574 } else {
1575 Timeout timeout = Timeout.parse(timeoutHeader);
1576 return new Timeout[]{timeout};
1577 }
1578 } else {
1579 return null;
1580 }
1581 }
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592 protected Object readRequestXML(Adaptable adaptable, Class<?> expectedClass) throws SAXException {
1593 InputStream inputStream = (InputStream)adaptable.adapt(InputStream.class);
1594 if ((inputStream instanceof HTTPBufferedInputStream)
1595 && (((HTTPBufferedInputStream)inputStream).getContentLength() == 0)) {
1596 return null;
1597 } else {
1598 try {
1599 SAXParserFactory parserFactory = SAXParserFactory.newInstance();
1600 SAXParser parser = parserFactory.newSAXParser();
1601 XMLReader reader = parser.getXMLReader();
1602 reader.setFeature("http://xml.org/sax/features/namespaces", true);
1603
1604 InputSource inputSource = new InputSource(inputStream);
1605 WebDAVXMLHandler webDAVXMLHandler = new WebDAVXMLHandler(adapter.getNamespacesProvider());
1606 parser.parse(inputSource, webDAVXMLHandler);
1607 Object result = webDAVXMLHandler.getResultObject();
1608 if ((result != null) && (expectedClass.isAssignableFrom(result.getClass()))) {
1609 return result;
1610 }
1611 } catch (ParserConfigurationException e) {
1612 e.printStackTrace();
1613 } catch (IOException e) {
1614 e.printStackTrace();
1615 }
1616 }
1617 return null;
1618 }
1619
1620
1621 }