1 package com.ibm.webdav.impl; 2 3 17 import java.io.*; 18 import java.net.*; 19 import java.util.*; 20 21 import org.w3c.dom.*; 22 23 import com.ibm.webdav.*; 24 import com.ibm.webdav.Collection; 25 26 35 public class CollectionImpl extends ResourceImpl implements IRCollection { 36 private Vector members = null; 37 public CollectionImpl() { 39 super(); 40 } 41 49 public CollectionImpl( 50 URL url, 51 String localName, 52 TargetSelector targetSelector) 53 throws WebDAVException { 54 super(url, localName); 55 String file = url.getFile(); 56 if (!file.endsWith("/")) { 57 file = file + "/"; 58 try { 59 this.url = new URL(url, file); 60 } catch (java.net.MalformedURLException exc) { 61 throw new WebDAVException( 62 WebDAVStatus.SC_BAD_REQUEST, 63 "Malformed URL"); 64 } 65 66 } 67 } 68 85 public MultiStatus copy( 86 ResourceContext context, 87 String destinationURL, 88 boolean overwrite, 89 Vector propertiesToCopy) 90 throws WebDAVException { 91 return copy( 92 context, 93 destinationURL, 94 overwrite, 95 propertiesToCopy, 96 Collection.deep); 97 } 98 120 public MultiStatus copy( 121 ResourceContext context, 122 String destinationURL, 123 boolean overwrite, 124 Vector propertiesToCopy, 125 String depth) 126 throws WebDAVException { 127 this.context = context; 128 129 setStatusCode(WebDAVStatus.SC_CREATED); 130 131 MultiStatus result = new MultiStatus(); 133 134 if (!hasValidURI()) { 136 throw new WebDAVException( 137 WebDAVStatus.SC_BAD_REQUEST, 138 "Invalid URI"); 139 } 140 141 if (!(depth.equals(Collection.shallow) 143 || depth.equals(Collection.deep))) { 144 throw new WebDAVException( 145 WebDAVStatus.SC_BAD_REQUEST, 146 "Invalid depth on copy"); 147 } 148 149 if (!exists()) { 151 throw new WebDAVException( 152 WebDAVStatus.SC_NOT_FOUND, 153 "Resource does not exist"); 154 } 155 156 Collection destination = null; 158 try { 159 URL destURL = new URL(getURL(), destinationURL); 160 destination = new Collection(destURL.toString()); 161 } catch (WebDAVException exc) { 162 throw exc; 163 } catch (java.net.MalformedURLException exc) { 164 } catch (java.io.IOException exc) { 165 throw new WebDAVException( 166 WebDAVStatus.SC_BAD_REQUEST, 167 "Malformed URL"); 168 } 169 170 if (this.equals(destination)) { 172 throw new WebDAVException( 173 WebDAVStatus.SC_FORBIDDEN, 174 "Can't copy source on top of itself"); 175 } 176 177 destination.getRequestContext().precondition( 179 getRequestContext().precondition()); 180 destination.getRequestContext().authorization( 181 getRequestContext().authorization()); 182 if (destination.exists() 183 && destination.isLocked() 184 && !destination.isLockedByMe()) { 185 throw new WebDAVException( 186 WebDAVStatus.SC_LOCKED, 187 "Destination resource is locked"); 188 } 189 190 if (destination.exists() && !overwrite) { 192 throw new WebDAVException( 193 WebDAVStatus.SC_PRECONDITION_FAILED, 194 "Destination exists and overwrite not specified"); 195 } 196 197 if (destination.exists()) { 200 destination.delete(); 201 setStatusCode(WebDAVStatus.SC_NO_CONTENT); 202 } 203 destination.createCollection(); 204 205 if (depth.equals(Collection.deep)) { 207 Enumeration members = namespaceManager.getMembers().elements(); 208 while (members.hasMoreElements()) { 209 ResourceImpl member = (ResourceImpl) members.nextElement(); 210 String thisURL = getURL().toString(); 212 String memberURL = member.getURL().toString(); 213 String memberPart = memberURL.substring(thisURL.length()); 214 String dest = destination.getURL().toString() + memberPart; 215 try { 216 MultiStatus memberResult = null; 217 if (member.isCollection()) { 218 memberResult = 219 ((CollectionImpl) member).copy( 220 context, 221 dest, 222 overwrite, 223 propertiesToCopy, 224 depth); 225 } else { 226 memberResult = 227 member.copy( 228 context, 229 dest, 230 overwrite, 231 propertiesToCopy); 232 } 233 if (!memberResult.isOK()) { 234 result.mergeWith(memberResult); 235 } 236 } catch (WebDAVException exc) { 237 MethodResponse response = 238 new MethodResponse( 239 member.getURL().toString(), 240 exc.getStatusCode()); 241 result.addResponse(response); 242 } catch (Exception e) { 243 e.printStackTrace(); 244 throw new WebDAVException( 245 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 246 "unable to delete resource"); 247 } 248 } 249 } 250 251 WebDAVStatus savedStatusCode = context.getStatusCode(); 253 MultiStatus ms2 = copyProperties(destination, propertiesToCopy); 255 if (!ms2.isOK()) { 256 throw new WebDAVException( 260 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 261 "problem copying properties"); 262 } 263 264 String authorization = getRequestContext().authorization(); 267 destination.getRequestContext().setBasicAuthorization("root", ""); 268 Enumeration locks = destination.getLocks().elements(); 269 while (locks.hasMoreElements()) { 270 ActiveLock lock = (ActiveLock) locks.nextElement(); 271 try { 273 destination.unlock(lock.getLockToken()); 274 } catch (Exception exc) { 275 } 276 } 277 destination.getRequestContext().authorization(authorization); 278 context.setStatusCode(savedStatusCode); 279 280 getResponseContext().contentType("text/xml"); 283 return result; 284 } 285 297 public MultiStatus createCollection( 298 ResourceContext context, 299 Document contents) 300 throws WebDAVException { 301 this.context = context; 302 303 setStatusCode(WebDAVStatus.SC_CREATED); 304 String fileName = ResourceFactory.getRealPath(getURL()); 305 306 if (!hasValidURI() || fileName.indexOf(File.separator) < 0) { 308 throw new WebDAVException( 309 WebDAVStatus.SC_BAD_REQUEST, 310 "Invalid URI"); 311 } 312 313 if (exists()) { 315 if (isCollection()) { 316 throw new WebDAVException( 317 WebDAVStatus.SC_METHOD_NOT_ALLOWED, 318 "Collection already exists"); 319 } else { 320 throw new WebDAVException( 321 WebDAVStatus.SC_METHOD_NOT_ALLOWED, 322 "Resource already exists"); 323 } 324 } 325 326 CollectionImpl parent = (CollectionImpl) getParentCollection(); 328 if (parent != null && !parent.exists()) { 329 throw new WebDAVException( 330 WebDAVStatus.SC_CONFLICT, 331 "Parent collection does not exist"); 332 } 333 334 if (parent != null) { 336 parent.getRequestContext().precondition( 337 getRequestContext().precondition()); 338 parent.getRequestContext().authorization( 339 getRequestContext().authorization()); 340 if (parent.isLocked() && !parent.isLockedByMe()) { 341 throw new WebDAVException( 342 WebDAVStatus.SC_LOCKED, 343 "Parent collection is locked by another user"); 344 } 345 } 346 347 if (contents != null) { 350 throw new WebDAVException( 351 WebDAVStatus.SC_UNSUPPORTED_MEDIA_TYPE, 352 "Creating collections from contents not supported yet"); 353 } 354 355 namespaceManager.createCollection( 357 ResourceFactory.getRealPath(getURL())); 358 359 Document properties = loadProperties(); 361 saveProperties(properties); 362 363 inheritParentDeepLocks(); 365 MultiStatus status = new MultiStatus(); 366 MethodResponse response = 367 new MethodResponse(getURL().toString(), WebDAVStatus.SC_CREATED); 368 status.addResponse(response); 369 getResponseContext().contentType("text/xml"); 370 return status; 371 } 372 381 public MultiStatus delete(ResourceContext context) throws WebDAVException { 382 this.context = context; 383 384 MultiStatus result = new MultiStatus(); 385 386 Enumeration members = namespaceManager.getMembers().elements(); 388 while (members.hasMoreElements()) { 389 ResourceImpl member = (ResourceImpl) members.nextElement(); 390 try { 391 MultiStatus memberResult = null; 392 memberResult = member.delete(context); 393 if (!memberResult.isOK()) { 394 result.mergeWith(memberResult); 395 } 396 } catch (WebDAVException exc) { 397 MethodResponse response = 398 new MethodResponse(member.getURL().toString(), exc); 399 result.addResponse(response); 400 } catch (Exception e) { 401 e.printStackTrace(); 402 throw new WebDAVException( 403 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 404 "unable to delete resource"); 405 } 406 } 407 408 if (result.isOK()) { 410 try { 411 MultiStatus thisResult = super.delete(context); 412 if (!thisResult.isOK()) { 413 result.mergeWith(thisResult); 414 } 415 } catch (WebDAVException exc) { 416 MethodResponse response = 418 new MethodResponse(getURL().toString(), exc); 419 result.addResponse(response); 420 } catch (Exception e) { 421 e.printStackTrace(); 422 throw new WebDAVException( 423 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 424 "unable to delete resource"); 425 } 426 } 427 getResponseContext().contentType("text/xml"); 428 return result; 429 } 430 442 protected MultiStatus doUnlock(String lockToken) throws WebDAVException { 443 445 MultiStatus result = new MultiStatus(); 446 447 ActiveLock lockToUnlock = null; 449 Enumeration activeLocks = getLocks().elements(); 450 while (activeLocks.hasMoreElements()) { 451 ActiveLock activeLock = (ActiveLock) activeLocks.nextElement(); 452 if (activeLock.getLockToken().equals(lockToken)) { 453 lockToUnlock = activeLock; 454 break; 455 } 456 } 457 458 if (lockToUnlock != null 461 && lockToUnlock.getDepth().equals(Collection.deep)) { 462 Enumeration members = namespaceManager.getMembers().elements(); 463 while (members.hasMoreElements()) { 464 ResourceImpl member = (ResourceImpl) members.nextElement(); 465 member.getRequestContext().precondition( 466 getRequestContext().precondition()); 467 member.getRequestContext().authorization( 468 getRequestContext().authorization()); 469 try { 470 MultiStatus memberResult = member.doUnlock(lockToken); 471 result.mergeWith(memberResult); 472 } catch (WebDAVException exc) { 473 MethodResponse response = 474 new MethodResponse( 475 member.getURL().toString(), 476 exc.getStatusCode()); 477 result.addResponse(response); 478 } catch (Exception e) { 479 e.printStackTrace(); 480 throw new WebDAVException( 481 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 482 "unable to delete resource"); 483 } 484 } 485 } 486 487 MultiStatus r = super.doUnlock(lockToken); 489 if (!r.isOK()) { 490 result.mergeWith(r); 491 } 492 getResponseContext().contentType("text/xml"); 493 return result; 494 } 495 502 public URL getChildURL(String childName) throws WebDAVException { 503 String uri = getURL().getFile(); 504 if (!uri.endsWith("/")) { 505 uri = uri + "/"; 506 } 507 URL child = null; 508 try { 509 child = new URL(getURL(), uri + childName); 510 } catch (java.net.MalformedURLException exc) { 511 throw new WebDAVException( 512 WebDAVStatus.SC_BAD_REQUEST, 513 "Malformed URL"); 514 } 515 return child; 516 } 517 525 public InputStream getContentsInputStream() throws WebDAVException { 526 if (!hasValidURI()) { 528 throw new WebDAVException( 529 WebDAVStatus.SC_BAD_REQUEST, 530 "Invalid URI"); 531 } 532 InputStream is = namespaceManager.getContentsInputStream(); 533 534 getResponseContext().contentType("text/xml"); 536 return is; 537 } 538 543 public OutputStream getContentsOutputStream() throws WebDAVException { 544 throw new WebDAVException( 545 WebDAVStatus.SC_METHOD_NOT_ALLOWED, 546 "Cannot use PUT on collections, use MKCOL instead."); 547 } 548 553 public Vector getMembers() throws WebDAVException { 554 return namespaceManager.getMembers(); 555 } 556 568 public MultiStatus getProperties( 569 ResourceContext context, 570 PropertyName names[], 571 String depth) 572 throws WebDAVException { 573 this.context = context; 574 575 if (!(depth.equals(Collection.thisResource) 577 || depth.equals(Collection.immediateMembers) 578 || depth.equals(Collection.allMembers))) { 579 throw new WebDAVException( 580 WebDAVStatus.SC_BAD_REQUEST, 581 "Invalid depth on copy"); 582 } 583 584 MultiStatus result = super.getProperties(context, names); 585 String memberDepth = depth; 586 if (depth.equals(Collection.immediateMembers)) { 587 memberDepth = Collection.thisResource; 588 } 589 590 if (!depth.equals(Collection.thisResource)) { 592 Enumeration members = namespaceManager.getMembers().elements(); 593 while (members.hasMoreElements()) { 594 ResourceImpl member = (ResourceImpl) members.nextElement(); 595 try { 596 MultiStatus memberResult = null; 597 if (member.isCollection()) { 598 memberResult = 599 ((CollectionImpl) member).getProperties( 600 context, 601 names, 602 memberDepth); 603 } else { 604 memberResult = member.getProperties(context, names); 605 } 606 result.mergeWith(memberResult); 607 } catch (WebDAVException exc) { 608 exc.printStackTrace(); 609 MethodResponse response = 610 new MethodResponse( 611 member.getURL().toString(), 612 exc.getStatusCode()); 613 result.addResponse(response); 614 } catch (Exception e) { 615 e.printStackTrace(); 616 throw new WebDAVException( 617 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 618 "Error getting properties"); 619 } 620 } 621 } 622 getResponseContext().contentType("text/xml"); 623 return result; 624 } 625 626 638 public MultiStatus getProperties(ResourceContext context, String depth) 639 throws WebDAVException { 640 this.context = context; 641 642 if (!(depth.equals(Collection.thisResource) 644 || depth.equals(Collection.immediateMembers) 645 || depth.equals(Collection.allMembers))) { 646 throw new WebDAVException( 647 WebDAVStatus.SC_BAD_REQUEST, 648 "Invalid depth on copy"); 649 } 650 651 MultiStatus result = super.getProperties(context); 652 String memberDepth = depth; 653 if (depth.equals(Collection.immediateMembers)) { 654 memberDepth = Collection.thisResource; 655 } 656 657 if (!depth.equals(Collection.thisResource)) { 659 Enumeration members = namespaceManager.getMembers().elements(); 660 while (members.hasMoreElements()) { 661 ResourceImpl member = (ResourceImpl) members.nextElement(); 662 try { 663 MultiStatus memberResult = null; 664 if (member.isCollection()) { 665 memberResult = 666 ((CollectionImpl) member).getProperties( 667 context, 668 memberDepth); 669 } else { 670 memberResult = member.getProperties(context); 671 } 672 result.mergeWith(memberResult); 673 } catch (WebDAVException exc) { 674 exc.printStackTrace(); 675 MethodResponse response = 676 new MethodResponse( 677 member.getURL().toString(), 678 exc.getStatusCode()); 679 result.addResponse(response); 680 } catch (Exception e) { 681 e.printStackTrace(); 682 throw new WebDAVException( 683 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 684 "unable to get properties"); 685 } 686 } 687 } 688 getResponseContext().contentType("text/xml"); 689 return result; 690 } 691 692 705 public MultiStatus getPropertyNames(ResourceContext context, String depth) 706 throws WebDAVException { 707 this.context = context; 708 709 if (!(depth.equals(Collection.thisResource) 711 || depth.equals(Collection.immediateMembers) 712 || depth.equals(Collection.allMembers))) { 713 throw new WebDAVException( 714 WebDAVStatus.SC_BAD_REQUEST, 715 "Invalid depth on copy"); 716 } 717 MultiStatus result = super.getPropertyNames(context); 718 String memberDepth = depth; 719 if (depth.equals(Collection.immediateMembers)) { 720 memberDepth = Collection.thisResource; 721 } 722 723 if (!depth.equals(Collection.thisResource)) { 725 Enumeration members = namespaceManager.getMembers().elements(); 726 while (members.hasMoreElements()) { 727 ResourceImpl member = (ResourceImpl) members.nextElement(); 728 try { 729 MultiStatus memberResult = null; 730 if (member.isCollection()) { 731 memberResult = 732 ((CollectionImpl) member).getPropertyNames( 733 context, 734 memberDepth); 735 } else { 736 memberResult = member.getPropertyNames(context); 737 } 738 result.mergeWith(memberResult); 739 } catch (WebDAVException exc) { 740 exc.printStackTrace(); 741 MethodResponse response = 742 new MethodResponse( 743 member.getURL().toString(), 744 exc.getStatusCode()); 745 result.addResponse(response); 746 } catch (Exception e) { 747 e.printStackTrace(); 748 throw new WebDAVException( 749 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 750 "unable to delete resource"); 751 } 752 } 753 } 754 getResponseContext().contentType("text/xml"); 755 return result; 756 } 757 762 public boolean isCollection() throws WebDAVException { 763 return true; 764 } 765 770 protected MultiStatus lock(ActiveLock activeLock) throws WebDAVException { 771 Enumeration locks = getLocks().elements(); 773 while (locks.hasMoreElements()) { 774 ActiveLock lock = (ActiveLock) locks.nextElement(); 775 if (lock.getScope().equals(ActiveLock.exclusive)) { 776 throw new WebDAVException( 777 WebDAVStatus.SC_LOCKED, 778 "Resource has an exclusive lock"); 779 } 780 if (lock.getScope().equals(ActiveLock.shared) 781 && activeLock.getScope().equals(ActiveLock.exclusive)) { 782 throw new WebDAVException( 783 WebDAVStatus.SC_LOCKED, 784 "Resource already has a shared lock"); 785 } 786 if (lock.getScope().equals(ActiveLock.shared) 787 && lock.getPrincipal().equals(activeLock.getPrincipal())) { 788 throw new WebDAVException( 789 WebDAVStatus.SC_LOCKED, 790 "The principal already has a lock on this resource"); 791 } 792 } 793 794 MultiStatus result = super.lock(activeLock); 796 797 if (activeLock.getDepth().equals(Collection.deep)) { 799 Enumeration members = namespaceManager.getMembers().elements(); 800 while (members.hasMoreElements()) { 801 ResourceImpl member = (ResourceImpl) members.nextElement(); 802 member.getRequestContext().precondition( 803 getRequestContext().precondition()); 804 member.getRequestContext().authorization( 805 getRequestContext().authorization()); 806 try { 807 MultiStatus memberResult = member.lock(activeLock); 808 result.mergeWith(memberResult); 809 } catch (WebDAVException exc) { 810 MethodResponse response = 811 new MethodResponse( 812 member.getURL().toString(), 813 exc.getStatusCode()); 814 result.addResponse(response); 815 } catch (Exception e) { 816 e.printStackTrace(); 817 throw new WebDAVException( 818 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 819 "unable to delete resource"); 820 } 821 } 822 } 823 824 return result; 825 } 826 843 public MultiStatus lock( 844 ResourceContext context, 845 String scope, 846 String type, 847 int timeout, 848 Element owner) 849 throws WebDAVException { 850 return lock(context, scope, type, timeout, owner, Collection.deep); 851 } 852 874 public MultiStatus lock( 875 ResourceContext context, 876 String scope, 877 String type, 878 int timeout, 879 Element owner, 880 String depth) 881 throws WebDAVException { 882 this.context = context; 883 884 if (!(depth.equals(Collection.shallow) 886 || depth.equals(Collection.deep))) { 887 throw new WebDAVException( 888 WebDAVStatus.SC_BAD_REQUEST, 889 "Invalid depth on copy"); 890 } 891 892 ActiveLock activeLock = getActiveLockFor(scope, type, timeout, owner); 894 activeLock.setDepth(depth); 895 MultiStatus result = lock(activeLock); 896 897 if (!result.isOK()) { 899 try { 900 unlock(context, activeLock.getLockToken()); 901 } catch (Exception exc) { 902 } 903 result.removeOKResponses(); 906 } 907 908 getResponseContext().lockToken(activeLock.getLockToken()); 910 getResponseContext().contentType("text/xml"); 911 return result; 912 } 913 923 public MultiStatus refreshLock( 924 ResourceContext context, 925 String lockToken, 926 int timeout) 927 throws WebDAVException { 928 this.context = context; 929 930 932 if (parentIsLockedWith(lockToken)) { 934 throw new WebDAVException( 935 WebDAVStatus.SC_METHOD_NOT_ALLOWED, 936 "Must refresh depth lock from root collection having the lock."); 937 } 938 939 MultiStatus result = super.refreshLock(context, lockToken, timeout); 941 942 ActiveLock lockToRefresh = null; 944 Enumeration activeLocks = getLocks().elements(); 945 while (activeLocks.hasMoreElements()) { 946 ActiveLock activeLock = (ActiveLock) activeLocks.nextElement(); 947 if (activeLock.getLockToken().equals(lockToken)) { 948 lockToRefresh = activeLock; 949 break; 950 } 951 } 952 953 if (lockToRefresh.getDepth().equals(Collection.deep)) { 956 Enumeration members = namespaceManager.getMembers().elements(); 957 while (members.hasMoreElements()) { 958 Resource member = (Resource) members.nextElement(); 959 member.getRequestContext().precondition( 960 getRequestContext().precondition()); 961 member.getRequestContext().authorization( 962 getRequestContext().authorization()); 963 try { 964 MultiStatus memberResult = 965 member.refreshLock(lockToken, timeout); 966 result.mergeWith(memberResult); 967 } catch (WebDAVException exc) { 968 MethodResponse response = 969 new MethodResponse( 970 member.getURL().toString(), 971 exc.getStatusCode()); 972 result.addResponse(response); 973 } catch (Exception e) { 974 e.printStackTrace(); 975 throw new WebDAVException( 976 WebDAVStatus.SC_INTERNAL_SERVER_ERROR, 977 "unable to delete resource"); 978 } 979 } 980 } 981 getResponseContext().contentType("text/xml"); 982 return result; 983 } 984 985 992 public MultiStatus setOrdering( 993 ResourceContext context, 994 Document orderPatch) 995 throws WebDAVException { 996 if (exists() == false) { 998 throw new WebDAVException( 999 WebDAVStatus.SC_NOT_FOUND, 1000 "Resource does not exist"); 1001 } 1002 1003 if (isCollection() == false) { 1004 throw new WebDAVException( 1005 WebDAVStatus.SC_BAD_REQUEST, 1006 "Resource is not collection"); 1007 } 1008 1009 if (isLocked() && isLockedByMe() == false) { 1011 throw new WebDAVException( 1012 WebDAVStatus.SC_LOCKED, 1013 "Resource is locked by another user"); 1014 } 1015 1016 MultiStatus result = new MultiStatus(); 1017 1018 try { 1019 namespaceManager.setOrdering(orderPatch); 1020 } catch (WebDAVException e) { 1021 result.addResponse(new MethodResponse(getURL().getPath(),e)); 1023 } 1024 1025 return result; 1026 } 1027} 1028 | Popular Tags |