1 package com.ibm.webdav.protocol.http; 2 3 17 import com.ibm.webdav.protocol.http.WebDAVURLConnection; 18 import com.ibm.webdav.protocol.http.WebDAVAuthenticator; 19 import com.ibm.webdav.*; 20 import com.ibm.webdav.impl.*; 21 import com.ibm.webdav.ServerException; 22 import java.io.*; 23 import java.net.URL ; 24 import org.w3c.dom.*; 25 import java.util.Vector ; 26 import java.util.Properties ; 27 import java.util.Enumeration ; 28 import javax.xml.parsers.*; 29 30 36 public class ResourceHTTPStub implements IRResource { 37 protected URL url = null; 38 39 protected ResourceContext context = new ResourceContext(); 41 42 static { 43 44 WebDAVURLConnection.setDefaultAuthenticator(new WebDAVAuthenticator()); 45 } 46 47 protected WebDAVURLConnection connection = null; 48 49 protected static Properties properties = ResourceFactory.properties; 51 53 public ResourceHTTPStub() { 54 this.url = null; 55 } 56 68 public ResourceHTTPStub(String url) throws java.io.IOException { 69 this(new URL (url), (TargetSelector)null); 70 } 71 81 public ResourceHTTPStub(String protocol, String host, int port, String file) throws java.io.IOException { 82 this(new URL (protocol, host, port, file), (TargetSelector)null); 83 } 84 94 public ResourceHTTPStub(String protocol, String host, String file) throws java.io.IOException { 95 this(new URL (protocol, host, file), (TargetSelector)null); 96 } 97 109 public ResourceHTTPStub(URL url, TargetSelector targetSelector) throws WebDAVException { 110 this.url = url; 111 } 112 124 public ResourceHTTPStub(URL context, String spec) throws java.io.IOException { 125 this(new URL (context, spec), (TargetSelector)null); 126 } 127 131 public void closeContentsOutputStream(ResourceContext context) throws WebDAVException { 132 this.closeContentsOutputStream(context, null); 133 } 134 135 public void closeContentsOutputStream(ResourceContext context,String sContentType) throws WebDAVException { 136 this.context = context; 137 138 getResults(); 139 } 140 157 public MultiStatus copy(ResourceContext context, String destinationURL, boolean overwrite, Vector propertiesToCopy) throws WebDAVException { 158 this.context = context; 159 160 context.getRequestContext().overwrite(overwrite ? "T" : "F"); 161 context.getRequestContext().destination(destinationURL); 162 163 setupRequest("COPY"); 164 165 return doCopyOrMove(propertiesToCopy); 166 } 167 175 public MultiStatus delete(ResourceContext context) throws WebDAVException { 176 this.context = context; 177 178 setupRequest("DELETE"); 179 getResults(); 180 181 return responseToMultiStatus(); 182 } 183 197 private MultiStatus doCopyOrMove(Vector properties) throws WebDAVException { 198 context.getRequestContext().contentType("text/xml"); 199 200 Document document = null; 202 try { 203 document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 204 } catch(Exception e) { 205 throw new WebDAVException(WebDAVStatus.SC_PROCESSING,e.getMessage()); 206 } 207 210 Element propertybehavior = document.createElementNS("DAV:","D:propertybehavior"); 211 propertybehavior.setAttribute("xmlns:D", "DAV:"); 212 document.appendChild(propertybehavior); 213 214 if (properties == null) { 215 propertybehavior.appendChild(document.createElementNS("DAV:","D:omit")); 216 } else { 217 Element keepalive = document.createElementNS("DAV:","D:keepalive"); 218 propertybehavior.appendChild(keepalive); 219 if (properties.isEmpty()) { 220 keepalive.appendChild(document.createTextNode("*")); 221 } else { 222 Enumeration props = properties.elements(); 223 while (props.hasMoreElements()) { 224 String uri = (String ) props.nextElement(); 225 Element href = document.createElementNS("DAV:","D:href"); 226 href.appendChild(document.createTextNode(uri)); 227 keepalive.appendChild(href); 228 } 229 } 230 } 231 232 connection.setDoOutput(true); 234 try { 235 Writer writer = new OutputStreamWriter(connection.getOutputStream(), Resource.defaultCharEncoding); 236 PrintWriter pw = new PrintWriter(writer, false); 237 pw.print(XMLUtility.printNode(document.getDocumentElement())); 238 pw.flush(); 240 getResults(); 241 } catch (java.io.UnsupportedEncodingException exc) { 242 throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST, "Unsupported encoding requiested"); 243 } catch (WebDAVException exc) { 244 throw exc; 245 } catch (java.io.IOException exc) { 246 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 247 } 248 return responseToMultiStatus(); 249 } 250 257 public InputStream getContentsInputStream(ResourceContext context) throws WebDAVException { 258 this.context = context; 259 260 setupRequest("GET"); 261 getResults(); 262 InputStream stream = null; 263 try { 264 stream = connection.getInputStream(); 265 } catch (WebDAVException exc) { 266 System.err.println("ResourceHTTPStub.getContentsInputStream: Exception -"); 267 exc.printStackTrace(System.err); 268 throw exc; 269 } catch (java.io.IOException exc) { 270 System.err.println("ResourceHTTPStub.getContentsInputStream: Exception -"); 271 exc.printStackTrace(System.err); 272 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 273 } 274 return stream; 275 } 276 283 public OutputStream getContentsOutputStream(ResourceContext context) throws WebDAVException { 284 this.context = context; 285 HTTPHeaders requestContext = context.getRequestContext(); 286 if (requestContext.contentType() == null) { 287 requestContext.contentType("text/plain"); 288 } 289 290 setupRequest("PUT"); 291 connection.setDoOutput(true); 292 OutputStream stream = null; 293 try { 294 stream = connection.getOutputStream(); 295 } catch (WebDAVException exc) { 296 throw exc; 297 } catch (java.io.IOException exc) { 298 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 299 } 300 return stream; 301 } 302 317 public void getMetaInformation(ResourceContext context) throws WebDAVException { 318 this.context = context; 319 320 setupRequest("HEAD"); 321 getResults(); 322 } 323 335 public MultiStatus getProperties(ResourceContext context) throws WebDAVException { 336 this.context = context; 337 context.getRequestContext().contentType("text/xml"); 338 if (context.getRequestContext().depth() == null) { 340 context.getRequestContext().depth(Collection.thisResource); 341 } 342 343 setupRequest("PROPFIND"); 344 345 Document requestBody = null; 346 try { 347 requestBody = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 348 } catch(Exception e) { 349 throw new WebDAVException(WebDAVStatus.SC_PROCESSING,e.getMessage()); 350 } 351 Element propfind = requestBody.createElementNS("DAV:","D:propfind"); 354 propfind.setAttribute("xmlns:D", "DAV:"); 355 requestBody.appendChild(propfind); 356 propfind.appendChild(requestBody.createElementNS("DAV:","D:allprop")); 357 358 connection.setDoOutput(true); 359 try { 360 Writer writer = new OutputStreamWriter(connection.getOutputStream(), Resource.defaultCharEncoding); 361 PrintWriter pw = new PrintWriter(writer, false); 362 pw.print(XMLUtility.printNode(requestBody.getDocumentElement())); 363 pw.flush(); 365 } catch (WebDAVException exc) { 366 throw exc; 367 } catch (java.io.IOException exc) { 368 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO error or bad encoding"); 369 } 370 371 getResults(); 372 373 return responseToMultiStatus(); 374 } 375 387 public MultiStatus getProperties(ResourceContext context, PropertyName names[]) throws WebDAVException { 388 this.context = context; 389 context.getRequestContext().contentType("text/xml"); 390 if (context.getRequestContext().depth() == null) { 392 context.getRequestContext().depth(Collection.thisResource); 393 } 394 395 setupRequest("PROPFIND"); 396 397 Document requestBody = null; 398 try { 399 requestBody = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 400 } catch(Exception e) { 401 throw new WebDAVException(WebDAVStatus.SC_PROCESSING,e.getMessage()); 402 } 403 Element propfind = requestBody.createElementNS("DAV:","D:propfind"); 406 propfind.setAttribute("xmlns:D", "DAV:"); 407 requestBody.appendChild(propfind); 408 Element prop = requestBody.createElementNS("DAV:","D:prop"); 409 propfind.appendChild( prop ); 410 for (int i = 0; i < names.length; i++) { 411 PropertyName name = names[i]; 414 Element el = requestBody.createElementNS("DAV:","D:"+name.getLocal()); 415 if (!name.getNamespace().equals("DAV:")) { 416 el.setAttribute( "xmlns:D", name.getNamespace()); 417 } 418 419 prop.appendChild( el ); 420 } 421 422 connection.setDoOutput(true); 423 try { 424 Writer writer = new OutputStreamWriter(connection.getOutputStream(), Resource.defaultCharEncoding); 425 PrintWriter pw = new PrintWriter(writer, false); 426 pw.print(XMLUtility.printNode(requestBody.getDocumentElement())); 427 pw.flush(); 429 } catch (WebDAVException exc) { 430 throw exc; 431 } catch (java.io.IOException exc) { 432 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO error or bad encoding"); 433 } 434 getResults(); 435 436 return responseToMultiStatus(); 437 } 438 451 public MultiStatus getPropertyNames(ResourceContext context) throws WebDAVException { 452 this.context = context; 453 context.getRequestContext().contentType("text/xml"); 454 if (context.getRequestContext().depth() == null) { 456 context.getRequestContext().depth(Collection.thisResource); 457 } 458 459 setupRequest("PROPFIND"); 460 461 Document requestBody = null; 462 try { 463 requestBody = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 464 } catch(Exception e) { 465 throw new WebDAVException(WebDAVStatus.SC_PROCESSING,e.getMessage()); 466 } 467 Element propfind = requestBody.createElementNS("DAV:","D:propfind"); 470 propfind.setAttribute("xmlns:D", "DAV:"); 471 requestBody.appendChild(propfind); 472 propfind.appendChild(requestBody.createElementNS("DAV:","D:propname")); 473 connection.setDoOutput(true); 474 475 try { 476 Writer writer = new OutputStreamWriter(connection.getOutputStream(), Resource.defaultCharEncoding); 477 PrintWriter pw = new PrintWriter(writer, false); 478 pw.print(XMLUtility.printNode(requestBody.getDocumentElement())); 479 pw.flush(); 481 } catch (WebDAVException exc) { 482 throw exc; 483 } catch (java.io.IOException exc) { 484 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO error or bad encoding"); 485 } 486 487 getResults(); 488 489 return responseToMultiStatus(); 490 } 491 495 protected byte[] getResponseEntity() throws WebDAVException { 496 byte[] data = new byte[0]; 497 try { 498 BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); 499 int length = (int) context.getResponseContext().contentLength(); 500 if (length != -1) { 501 int rcvd = 0; 502 int size = 0; 503 data = new byte[length]; 504 do { 505 size += rcvd; 506 rcvd = is.read(data, size, length - size); 507 } while (size < length && rcvd != -1); 508 if (rcvd == -1) 509 data = resizeArray(data, size); 511 } else { 512 data = new byte[0]; 513 int inc = 8192; 514 int off = data.length; 515 int rcvd = 0; 516 do { 517 off += rcvd; 518 data = resizeArray(data, off + inc); 519 rcvd = is.read(data, off, inc); 520 } while (rcvd != -1); 521 data = resizeArray(data, off); 522 } 523 } catch (WebDAVException exc) { 524 throw exc; 525 } catch (java.io.IOException exc) { 526 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 527 } 528 return data; 529 } 530 535 protected void getResults() throws WebDAVException { 536 String statusMessage = null; 538 int responseCode = 0; 539 try { 540 responseCode = connection.getResponseCode(); 541 context.getStatusCode().setStatusCode(responseCode); 542 statusMessage = connection.getResponseMessage(); 543 } catch (WebDAVException exc) { 544 throw exc; 545 } catch (java.io.IOException exc) { 546 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 547 } 548 549 if (statusMessage == null || statusMessage.equals("Unknown")) { 550 statusMessage = context.getStatusCode().getStatusMessage(); 551 } 552 int i = 1; 555 String name = null; 556 while ((name = connection.getHeaderFieldKey(i)) != null) { 557 name = name.toLowerCase(); 558 String value = connection.getHeaderField(i); 559 context.getResponseContext().put(name, value); 560 i++; 561 } 562 563 if (responseCode >= 300 && responseCode <= 399) { 564 throw new RedirectionException(responseCode, statusMessage); 565 } else if (responseCode >= 400 && responseCode <= 499) { 566 throw new ClientException(responseCode, statusMessage); 567 } else if (responseCode >= 500 && responseCode <= 599) { 568 throw new ServerException(responseCode, statusMessage); 569 } 570 } 571 588 public MultiStatus lock(ResourceContext context, String scope, String type, int timeout, Element owner) throws WebDAVException { 589 this.context = context; 590 591 context.getRequestContext().contentType("text/xml"); 592 context.getRequestContext().setTimeout(timeout); 593 context.getRequestContext().precondition((String ) null); 594 if (context.getRequestContext().depth() == null) { 596 context.getRequestContext().depth(Collection.thisResource); 597 } 598 599 setupRequest("LOCK"); 600 601 Document requestBody = null; 603 try { 604 requestBody = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 605 } catch(Exception e) { 606 throw new WebDAVException(WebDAVStatus.SC_PROCESSING,e.getMessage()); 607 } 608 Element lockinfo = requestBody.createElementNS("DAV:","D:lockinfo"); 611 lockinfo.setAttribute("xmlns:D", "DAV:"); 612 requestBody.appendChild(lockinfo); 613 Element lockscope = requestBody.createElementNS("DAV:","D:lockscope"); 614 lockscope.appendChild(requestBody.createElementNS("DAV:","D:" + scope)); 615 lockinfo.appendChild(lockscope); 616 Element locktype = requestBody.createElementNS("DAV:","D:locktype"); 617 locktype.appendChild(requestBody.createElementNS("DAV:","D:" + type)); 618 lockinfo.appendChild(locktype); 619 if (owner != null) { 620 lockinfo.appendChild((Element) owner); 621 } 622 623 connection.setDoOutput(true); 625 try { 626 PrintWriter pw = new PrintWriter(connection.getOutputStream(), false); 627 pw.print(XMLUtility.printNode(requestBody.getDocumentElement())); 628 } catch (WebDAVException exc) { 630 throw exc; 631 } catch (java.io.IOException exc) { 632 System.err.println(exc); 633 exc.printStackTrace(); 634 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 635 } 636 637 getResults(); 639 640 return lockResponseToMultiStatus(); 641 } 642 647 protected MultiStatus lockResponseToMultiStatus() throws WebDAVException { 648 WebDAVErrorHandler errorHandler = new WebDAVErrorHandler(url.toString()); 650 Reader reader = null; 651 Document document = null; 652 653 656 657 658 try { 659 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 660 factory.setNamespaceAware(true); 661 DocumentBuilder docbuilder = factory.newDocumentBuilder(); 662 docbuilder.setErrorHandler(errorHandler); 663 reader = new InputStreamReader(connection.getInputStream(), Resource.defaultCharEncoding); 664 document = docbuilder.parse(new org.xml.sax.InputSource (reader)); 665 } catch (WebDAVException exc) { 666 throw exc; 667 } catch (java.io.IOException exc) { 668 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 669 } catch (Exception exc) { 670 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, exc.getMessage()); 671 } 672 673 674 if (errorHandler.getErrorCount() > 0) { 675 context.getStatusCode().setStatusCode(WebDAVStatus.SC_INTERNAL_SERVER_ERROR); 676 throw new ServerException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "Syntax error in multistatus response entity body"); 677 } 678 679 if (context.getStatusCode().getStatusCode() != WebDAVStatus.SC_MULTI_STATUS) { 681 Element prop = document.getDocumentElement(); 684 Element response = document.createElementNS("DAV:","D:response"); 685 686 Element href = document.createElementNS("DAV:","D:href"); 687 href.appendChild(document.createTextNode(url.toString())); 688 689 Element status = document.createElementNS("DAV:","D:status"); 690 String statusText = Response.HTTPVersion + " " + context.getStatusCode().getStatusCode() + " " + context.getStatusCode().getStatusMessage(); 691 status.appendChild(document.createTextNode(statusText)); 692 693 Element propstat = document.createElementNS("DAV:","D:propstat"); 694 propstat.appendChild((Element) ((Element) prop).cloneNode(true)); 695 propstat.appendChild(status); 696 response.appendChild(href); 697 response.appendChild(propstat); 698 699 Element multistatus = document.createElementNS("DAV:","D:multistatus"); 700 multistatus.setAttribute("xmlns:D", "DAV:"); 701 multistatus.appendChild(response); 702 Document newDocument = null; 703 try { 704 newDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 705 } catch(Exception exc) { 706 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, exc.getMessage()); 707 } 708 document = newDocument; 711 } 712 MultiStatus multiStatus = new MultiStatus(document); 713 return multiStatus; 714 } 715 732 public MultiStatus move(ResourceContext context, String destinationURL, boolean overwrite, Vector propertiesToMove) throws WebDAVException { 733 this.context = context; 734 735 context.getRequestContext().depth(Collection.deep); context.getRequestContext().overwrite(overwrite ? "T" : "F"); 737 context.getRequestContext().destination(destinationURL); 738 739 setupRequest("MOVE"); 740 741 return doCopyOrMove(propertiesToMove); 742 } 743 755 public byte[] performWith(ResourceContext context, String args) throws WebDAVException { 756 this.context = context; 757 758 setupRequest("POST"); 759 putRequestEntity(args.getBytes()); 760 getResults(); 761 return getResponseEntity(); 762 } 763 767 protected void putRequestEntity(byte[] value) throws WebDAVException { 768 connection.setDoOutput(true); 769 try { 770 BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream()); 771 outputStream.write(value, 0, value.length); 772 outputStream.flush(); 773 } catch (WebDAVException exc) { 774 throw exc; 775 } catch (java.io.IOException exc) { 776 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 777 } 778 } 779 789 public MultiStatus refreshLock(ResourceContext context, String lockToken, int timeout) throws WebDAVException { 790 this.context = context; 791 792 context.getRequestContext().precondition("(<" + lockToken + ">)"); 795 context.getRequestContext().setTimeout(timeout); 796 context.getRequestContext().depth(Collection.thisResource); 798 799 setupRequest("LOCK"); 801 802 getResults(); 804 return lockResponseToMultiStatus(); 805 } 806 811 private final static byte[] resizeArray(byte[] src, int new_size) { 812 byte tmp[] = new byte[new_size]; 813 System.arraycopy(src, 0, tmp, 0, (src.length < new_size ? src.length : new_size)); 814 return tmp; 815 } 816 821 protected MultiStatus responseToMultiStatus() throws WebDAVException { 822 MultiStatus multiStatus = null; 823 if (context.getStatusCode().getStatusCode() == WebDAVStatus.SC_MULTI_STATUS) { 824 BufferedReader reader = null; 825 Document document = null; 826 WebDAVErrorHandler errorHandler = new WebDAVErrorHandler(url.toString()); 828 829 830 try { 831 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 832 factory.setNamespaceAware(true); 833 DocumentBuilder docbuilder = factory.newDocumentBuilder(); 834 docbuilder.setErrorHandler(errorHandler); 835 838 839 840 reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Resource.defaultCharEncoding)); 841 document = docbuilder.parse(new org.xml.sax.InputSource (reader)); 842 } catch (WebDAVException exc) { 843 throw exc; 844 } catch (java.io.IOException exc) { 845 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error or bad encoding"); 846 } catch (Exception exc) { 847 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, exc.getMessage()); 848 } 849 850 if (errorHandler.getErrorCount() > 0) { 851 context.getStatusCode().setStatusCode(WebDAVStatus.SC_INTERNAL_SERVER_ERROR); 852 throw new ServerException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "Syntax error in multistatus response entity body"); 853 } 854 multiStatus = new MultiStatus(document); 855 } else { 856 multiStatus = new MultiStatus(); 857 MethodResponse response = new MethodResponse(url.toString(), context.getStatusCode().getStatusCode()); 858 response.setDescription(context.getStatusCode().getStatusMessage()); 859 multiStatus.addResponse(response); 860 } 861 return multiStatus; 862 } 863 871 public MultiStatus setProperties(ResourceContext context, Document updates) throws WebDAVException { 872 this.context = context; 873 context.getRequestContext().contentType("text/xml"); 874 875 setupRequest("PROPPATCH"); 876 877 connection.setDoOutput(true); 879 try { 880 PrintWriter pw = new PrintWriter(connection.getOutputStream(), false); 881 pw.print(XMLUtility.printNode(updates.getDocumentElement())); 882 883 } catch (WebDAVException exc) { 885 throw exc; 886 } catch (java.io.IOException exc) { 887 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 888 } 889 890 getResults(); 891 892 return responseToMultiStatus(); 893 } 894 899 protected void setupRequest(String method) throws WebDAVException { 900 try { 902 connection = new WebDAVURLConnection(url,"localhost",url.getPort()); 903 904 connection.setRequestMethod(method); 906 } catch (java.net.ProtocolException exc) { 907 exc.printStackTrace(); 908 } catch (WebDAVException exc) { 909 throw exc; 910 } catch (java.io.IOException exc) { 911 throw new WebDAVException(WebDAVStatus.SC_INTERNAL_SERVER_ERROR, "IO Error"); 912 } 913 914 Enumeration propertyNames = context.getRequestContext().keys(); 916 while (propertyNames.hasMoreElements()) { 917 String name = (String ) propertyNames.nextElement(); 918 String value = (String ) context.getRequestContext().get(name); 919 connection.setRequestProperty(name, value); 920 } 921 } 922 932 public MultiStatus unlock(ResourceContext context, String lockToken) throws WebDAVException { 933 this.context = context; 934 935 context.getRequestContext().lockToken(lockToken); 936 937 setupRequest("UNLOCK"); 938 939 getResults(); 941 942 return responseToMultiStatus(); 943 } 944 } 945 | Popular Tags |