1 16 package org.apache.cocoon.components.source.impl; 17 18 import java.io.BufferedInputStream ; 19 import java.io.ByteArrayInputStream ; 20 import java.io.ByteArrayOutputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.io.OutputStream ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Enumeration ; 27 import java.util.Properties ; 28 import java.util.Vector ; 29 30 import javax.xml.transform.OutputKeys ; 31 import javax.xml.transform.TransformerFactory ; 32 import javax.xml.transform.sax.SAXTransformerFactory ; 33 import javax.xml.transform.sax.TransformerHandler ; 34 import javax.xml.transform.stream.StreamResult ; 35 36 import org.apache.avalon.framework.logger.AbstractLogEnabled; 37 import org.apache.avalon.framework.logger.Logger; 38 import org.apache.cocoon.components.source.InspectableSource; 39 import org.apache.cocoon.components.source.helpers.SourceProperty; 40 import org.apache.cocoon.xml.XMLUtils; 41 import org.apache.commons.httpclient.HttpException; 42 import org.apache.commons.httpclient.HttpStatus; 43 import org.apache.commons.httpclient.HttpURL; 44 import org.apache.commons.httpclient.HttpsURL; 45 import org.apache.commons.httpclient.URIException; 46 import org.apache.excalibur.source.ModifiableSource; 47 import org.apache.excalibur.source.ModifiableTraversableSource; 48 import org.apache.excalibur.source.MoveableSource; 49 import org.apache.excalibur.source.Source; 50 import org.apache.excalibur.source.SourceException; 51 import org.apache.excalibur.source.SourceNotFoundException; 52 import org.apache.excalibur.source.SourceParameters; 53 import org.apache.excalibur.source.SourceUtil; 54 import org.apache.excalibur.source.SourceValidity; 55 import org.apache.excalibur.source.TraversableSource; 56 import org.apache.excalibur.source.impl.validity.TimeStampValidity; 57 import org.apache.webdav.lib.Property; 58 import org.apache.webdav.lib.PropertyName; 59 import org.apache.webdav.lib.ResponseEntity; 60 import org.apache.webdav.lib.WebdavResource; 61 import org.apache.webdav.lib.methods.DepthSupport; 62 import org.w3c.dom.Element ; 63 import org.w3c.dom.Node ; 64 import org.w3c.dom.NodeList ; 65 import org.w3c.dom.Text ; 66 import org.xml.sax.ContentHandler ; 67 import org.xml.sax.SAXException ; 68 import org.xml.sax.helpers.AttributesImpl ; 69 70 90 public class WebDAVSource extends AbstractLogEnabled 91 implements Source, TraversableSource, ModifiableSource, 92 ModifiableTraversableSource, InspectableSource, MoveableSource { 93 94 private static final String NAMESPACE = "http://apache.org/cocoon/webdav/1.0"; 95 96 private static final String PREFIX = "webdav"; 97 private static final String RESOURCE_NAME = "resource"; 98 private static final String COLLECTION_NAME = "collection"; 99 100 private final HttpURL url; 102 103 private final String protocol; 105 106 private String uri; 108 private String secureUri; 109 110 private WebdavResource resource = null; 112 113 private int depth = -1; 115 private int action = -1; 116 117 120 private WebDAVSource(HttpURL url, String protocol) throws URIException { 121 this.protocol = protocol; 122 this.url = url; 123 124 String qs = url.getQuery(); 125 if (qs != null) { 126 final SourceParameters sp = new SourceParameters(qs); 127 128 this.depth = sp.getParameterAsInteger("cocoon:webdav-depth", DepthSupport.DEPTH_1); 130 this.action = sp.getParameterAsInteger("cocoon:webdav-action", WebdavResource.NOACTION); 131 132 String principal = url.getUser(); 134 String password = url.getPassword(); 135 if (principal == null || password == null) { 136 principal = sp.getParameter("cocoon:webdav-principal", principal); 137 password = sp.getParameter("cocoon:webdav-password", password); 138 if (principal != null) { 139 url.setUser(principal); 140 url.setPassword(password); 141 } 142 } 143 144 sp.removeParameter("cocoon:webdav-depth"); 145 sp.removeParameter("cocoon:webdav-action"); 146 sp.removeParameter("cocoon:webdav-principal"); 147 sp.removeParameter("cocoon:webdav-password"); 148 149 url.setQuery(sp.getQueryString()); 151 } 152 } 153 154 157 private WebDAVSource (WebdavResource resource, HttpURL url, String protocol) 158 throws URIException { 159 this(url, protocol); 160 this.resource = resource; 161 } 162 163 194 private void initResource(int action, int depth) throws SourceException, SourceNotFoundException { 195 try { 196 boolean update = false; 197 if (action != WebdavResource.NOACTION) { 198 if (action > this.action) { 199 this.action = action; 200 update = true; 201 } else { 202 action = this.action; 203 } 204 } 205 if (depth > this.depth) { 206 this.depth = depth; 207 update = true; 208 } else { 209 depth = this.depth; 210 } 211 if (this.resource == null) { 212 this.resource = new WebdavResource(this.url, action, depth); 213 } else if (update) { 214 this.resource.setProperties(action, depth); 215 } 216 if (this.action > WebdavResource.NOACTION) { 217 if (this.resource.isCollection()) { 218 String path = this.url.getPath(); 219 if (path.charAt(path.length()-1) != '/') { 220 this.url.setPath(path + "/"); 221 } 222 } 223 } 224 } catch (HttpException e) { 225 if (e.getReasonCode() == HttpStatus.SC_NOT_FOUND) { 226 throw new SourceNotFoundException("Not found: " + getSecureURI(), e); 227 } 228 final String msg = "Could not initialize webdav resource at " + getSecureURI() 229 + ". Server responded " + e.getReasonCode() + " (" + e.getReason() + ") - " + e.getMessage(); 230 throw new SourceException(msg, e); 231 } catch (IOException e) { 232 throw new SourceException("Could not initialize webdav resource", e); 233 } 234 } 235 236 239 public static WebDAVSource newWebDAVSource(HttpURL url, 240 String protocol, 241 Logger logger) 242 throws URIException { 243 final WebDAVSource source = new WebDAVSource(url, protocol); 244 source.enableLogging(logger); 245 return source; 246 } 247 248 251 private static WebDAVSource newWebDAVSource(WebdavResource resource, 252 HttpURL url, 253 String protocol, 254 Logger logger) 255 throws URIException { 256 final WebDAVSource source = new WebDAVSource(resource, url, protocol); 257 source.enableLogging(logger); 258 return source; 259 } 260 261 263 266 public String getScheme() { 267 return this.protocol; 268 } 269 270 273 public String getURI() { 274 if (this.uri == null) { 275 String uri = this.url.toString(); 276 final int index = uri.indexOf("://"); 277 if (index != -1) { 278 uri = uri.substring(index+3); 279 } 280 final String userinfo = this.url.getEscapedUserinfo(); 281 if (userinfo != null) { 282 uri = this.protocol + "://" + userinfo + "@" + uri; 283 } else { 284 uri = this.protocol + "://" + uri; 285 } 286 this.uri = uri; 287 } 288 return this.uri; 289 } 290 291 294 protected String getSecureURI() { 295 if (this.secureUri == null) { 296 String uri = this.url.toString(); 297 int index = uri.indexOf("://"); 298 if (index != -1) { 299 uri = uri.substring(index+3); 300 } 301 uri = this.protocol + "://" + uri; 302 this.secureUri = uri; 303 } 304 return this.secureUri; 305 } 306 307 313 public SourceValidity getValidity() { 314 final long lm = getLastModified(); 315 if (lm > 0) { 316 return new TimeStampValidity(lm); 317 } 318 return null; 319 } 320 321 325 public void refresh() { 326 this.resource = null; 327 } 328 329 335 public InputStream getInputStream() throws IOException , SourceException { 336 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 337 try { 338 if (this.resource.isCollection()) { 339 WebdavResource[] resources = this.resource.listWebdavResources(); 342 return resourcesToXml(resources); 343 } else { 344 BufferedInputStream bi = null; 345 bi = new BufferedInputStream (this.resource.getMethodData()); 346 if (!this.resource.exists()) { 347 throw new HttpException(getSecureURI() + " does not exist"); 348 } 349 return bi; 350 } 351 } catch (HttpException he) { 352 throw new SourceException("Could not get WebDAV resource " + getSecureURI(), he); 353 } catch (Exception e) { 354 throw new SourceException("Could not get WebDAV resource" + getSecureURI(), e); 355 } 356 } 357 358 363 public String getMimeType() { 364 try { 365 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 366 } catch (IOException e) { 367 return null; 368 } 369 return this.resource.getGetContentType(); 370 } 371 372 376 public long getContentLength() { 377 try { 378 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 379 } 380 catch(IOException e) { 381 return -1; 382 } 383 if (this.resource.isCollection()) { 384 return -1; 385 } 386 return this.resource.getGetContentLength(); 387 } 388 389 394 public long getLastModified() { 395 try { 396 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 397 } catch(IOException e) { 398 return 0; 399 } 400 return this.resource.getGetLastModified(); 401 } 402 403 408 public boolean exists() { 409 try { 410 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 411 } catch (SourceNotFoundException e) { 412 return false; 413 } catch(IOException e) { 414 return true; 415 } 416 return this.resource.getExistence(); 417 } 418 419 private InputStream resourcesToXml(WebdavResource[] resources) 420 throws Exception { 421 TransformerFactory tf = TransformerFactory.newInstance(); 422 TransformerHandler th = ((SAXTransformerFactory ) tf).newTransformerHandler(); 423 ByteArrayOutputStream bOut = new ByteArrayOutputStream (); 424 StreamResult result = new StreamResult (bOut); 425 th.setResult(result); 426 th.startDocument(); 427 th.startPrefixMapping(PREFIX, NAMESPACE); 428 th.startElement(NAMESPACE, COLLECTION_NAME, PREFIX + ":" + COLLECTION_NAME, XMLUtils.EMPTY_ATTRIBUTES); 429 resourcesToSax(resources, th); 430 th.endElement(NAMESPACE, COLLECTION_NAME, PREFIX + ":" + COLLECTION_NAME); 431 th.endPrefixMapping(PREFIX); 432 th.endDocument(); 433 434 return new ByteArrayInputStream (bOut.toByteArray()); 435 } 436 437 private void resourcesToSax( 438 WebdavResource[] resources, 439 ContentHandler handler) 440 throws SAXException { 441 for (int i = 0; i < resources.length; i++) { 442 if (getLogger().isDebugEnabled()) { 443 final String message = 444 "RESOURCE: " + resources[i].getDisplayName(); 445 getLogger().debug(message); 446 } 447 if (resources[i].isCollection()) { 448 try { 449 WebdavResource[] childs = 450 resources[i].listWebdavResources(); 451 AttributesImpl attrs = new AttributesImpl (); 452 attrs.addAttribute( 453 NAMESPACE, 454 COLLECTION_NAME, 455 PREFIX + ":name", 456 "CDATA", 457 resources[i].getDisplayName()); 458 handler.startElement( 459 NAMESPACE, 460 COLLECTION_NAME, 461 PREFIX + ":" + COLLECTION_NAME, 462 attrs); 463 this.resourcesToSax(childs, handler); 464 handler.endElement( 465 NAMESPACE, 466 COLLECTION_NAME, 467 PREFIX + ":" + COLLECTION_NAME); 468 } catch (HttpException e) { 469 if (getLogger().isDebugEnabled()) { 470 final String message = 471 "Unable to get WebDAV children. Server responded " + 472 e.getReasonCode() + " (" + e.getReason() + ") - " 473 + e.getMessage(); 474 getLogger().debug(message); 475 } 476 } catch (SAXException e) { 477 if (getLogger().isDebugEnabled()) { 478 final String message = 479 "Unable to get WebDAV children: " 480 + e.getMessage(); 481 getLogger().debug(message,e); 482 } 483 } catch (IOException e) { 484 if (getLogger().isDebugEnabled()) { 485 final String message = 486 "Unable to get WebDAV children: " 487 + e.getMessage(); 488 getLogger().debug(message,e); 489 } 490 } catch (Exception e) { 491 if (getLogger().isDebugEnabled()) { 492 final String message = 493 "Unable to get WebDAV children: " 494 + e.getMessage(); 495 getLogger().debug(message,e); 496 } 497 } 498 } else { 499 AttributesImpl attrs = new AttributesImpl (); 500 attrs.addAttribute( 501 NAMESPACE, 502 "name", 503 PREFIX + ":name", 504 "CDATA", 505 resources[i].getDisplayName()); 506 handler.startElement( 507 NAMESPACE, 508 RESOURCE_NAME, 509 PREFIX + ":" + RESOURCE_NAME, 510 attrs); 511 handler.endElement( 512 NAMESPACE, 513 RESOURCE_NAME, 514 PREFIX + ":" + RESOURCE_NAME); 515 } 516 } 517 } 518 519 521 526 public Source getChild(String childName) throws SourceException { 527 if (!isCollection()) { 528 throw new SourceException(getSecureURI() + " is not a collection."); 529 } 530 try { 531 HttpURL childURL; 532 if (this.url instanceof HttpsURL) { 533 childURL = new HttpsURL((HttpsURL) this.url, childName); 534 } else { 535 childURL = new HttpURL(this.url, childName); 536 } 537 return WebDAVSource.newWebDAVSource(childURL, this.protocol, getLogger()); 538 } catch (URIException e) { 539 throw new SourceException("Failed to create child", e); 540 } 541 } 542 543 548 public Collection getChildren() throws SourceException { 549 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_1); 550 ArrayList children = new ArrayList (); 551 try { 552 WebdavResource[] resources = this.resource.listWebdavResources(); 553 for (int i = 0; i < resources.length; i++) { 554 HttpURL childURL; 555 if (this.url instanceof HttpsURL) { 556 childURL = new HttpsURL((HttpsURL) this.url,resources[i].getName()); 557 } else { 558 childURL = new HttpURL(this.url,resources[i].getName()); 559 } 560 WebDAVSource src = WebDAVSource.newWebDAVSource(resources[i], 561 childURL, 562 this.protocol, 563 getLogger()); 564 src.enableLogging(getLogger()); 565 children.add(src); 566 } 567 } catch (HttpException e) { 568 if (getLogger().isDebugEnabled()) { 569 final String message = 570 "Unable to get WebDAV children. Server responded " + 571 e.getReasonCode() + " (" + e.getReason() + ") - " 572 + e.getMessage(); 573 getLogger().debug(message); 574 } 575 throw new SourceException("Failed to get WebDAV collection children.", e); 576 } catch (SourceException e) { 577 throw e; 578 } catch (IOException e) { 579 throw new SourceException("Failed to get WebDAV collection children.", e); 580 } 581 return children; 582 } 583 584 588 public String getName() { 589 try { 590 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 591 } 592 catch (IOException e) { 593 return ""; 594 } 595 return this.resource.getName(); 596 } 597 598 603 public Source getParent() throws SourceException { 604 String path; 605 if (this.url.getEscapedPath().endsWith("/")) { 606 path = ".."; 607 } 608 else { 609 path = "."; 610 } 611 try { 612 HttpURL parentURL; 613 if (url instanceof HttpsURL) { 614 parentURL = new HttpsURL((HttpsURL) this.url, path); 615 } else { 616 parentURL = new HttpURL(this.url, path); 617 } 618 return WebDAVSource.newWebDAVSource(parentURL, this.protocol, getLogger()); 619 } catch (URIException e) { 620 throw new SourceException("Failed to create parent", e); 621 } 622 } 623 624 628 public boolean isCollection() { 629 try { 630 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 631 } 632 catch (IOException e) { 633 return false; 634 } 635 return this.resource.isCollection(); 636 } 637 638 640 647 public OutputStream getOutputStream() throws IOException { 648 return new WebDAVSourceOutputStream(this); 649 } 650 651 657 public boolean canCancel(OutputStream stream) { 658 if (stream instanceof WebDAVSourceOutputStream) { 659 WebDAVSourceOutputStream wsos = (WebDAVSourceOutputStream) stream; 660 if (wsos.source == this) { 661 return wsos.canCancel(); 662 } 663 } 664 throw new IllegalArgumentException ("The stream is not associated to this source"); 665 } 666 667 673 public void cancel(OutputStream stream) throws SourceException { 674 if (stream instanceof WebDAVSourceOutputStream) { 675 WebDAVSourceOutputStream wsos = (WebDAVSourceOutputStream) stream; 676 if (wsos.source == this) { 677 try { 678 wsos.cancel(); 679 } 680 catch (Exception e) { 681 throw new SourceException("Failure cancelling Source", e); 682 } 683 } 684 } 685 throw new IllegalArgumentException ("The stream is not associated to this source"); 686 } 687 688 692 public void delete() throws SourceException { 693 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 694 try { 695 this.resource.deleteMethod(); 696 } catch (HttpException e) { 697 throw new SourceException("Unable to delete source: " + getSecureURI(), e); 698 } catch (IOException e) { 699 throw new SourceException("Unable to delete source: " + getSecureURI(), e); 700 } 701 } 702 703 private static class WebDAVSourceOutputStream extends ByteArrayOutputStream { 704 705 private WebDAVSource source = null; 706 private boolean isClosed = false; 707 708 private WebDAVSourceOutputStream(WebDAVSource source) { 709 this.source = source; 710 } 711 712 public void close() throws IOException { 713 if (!isClosed) { 714 try { 715 super.close(); 716 this.source.initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 717 this.source.resource.putMethod(toByteArray()); 718 } catch (HttpException he) { 719 final String message = 720 "Unable to close output stream. Server responded " + 721 he.getReasonCode() + " (" + he.getReason() + ") - " 722 + he.getMessage(); 723 this.source.getLogger().debug(message); 724 throw new IOException (he.getMessage()); 725 } 726 finally { 727 this.isClosed = true; 728 } 729 } 730 } 731 732 private boolean canCancel() { 733 return !isClosed; 734 } 735 736 private void cancel() { 737 if (isClosed) { 738 throw new IllegalStateException ("Cannot cancel: outputstream is already closed"); 739 } 740 this.isClosed = true; 741 } 742 } 743 744 746 750 public void makeCollection() throws SourceException { 751 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 752 if (this.resource.exists()) return; 753 try { 754 if (!this.resource.mkcolMethod()) { 755 int status = this.resource.getStatusCode(); 756 if (status == 409) { 757 ((ModifiableTraversableSource) getParent()).makeCollection(); 759 makeCollection(); 760 } 761 else if (status == 404) { 762 ((ModifiableTraversableSource) getParent()).makeCollection(); 765 makeCollection(); 766 } 767 else if (status != 405) { 769 final String msg = 770 "Unable to create collection " + getSecureURI() 771 + ". Server responded " + this.resource.getStatusCode() 772 + " (" + this.resource.getStatusMessage() + ")"; 773 throw new SourceException(msg); 774 } 775 } 776 } catch (HttpException e) { 777 throw new SourceException("Unable to create collection(s) " + getSecureURI(), e); 778 } catch (SourceException e) { 779 throw e; 780 } catch (IOException e) { 781 throw new SourceException("Unable to create collection(s)" + getSecureURI(), e); 782 } 783 } 784 785 787 794 public SourceProperty[] getSourceProperties() throws SourceException { 795 796 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 797 798 Vector sourceproperties = new Vector (); 799 Enumeration props= null; 800 org.apache.webdav.lib.Property prop = null; 801 802 try { 803 Enumeration responses = this.resource.propfindMethod(0); 804 while (responses.hasMoreElements()) { 805 806 ResponseEntity response = (ResponseEntity)responses.nextElement(); 807 props = response.getProperties(); 808 while (props.hasMoreElements()) { 809 prop = (Property) props.nextElement(); 810 SourceProperty srcProperty = new SourceProperty(prop.getElement()); 811 sourceproperties.addElement(srcProperty); 812 } 813 } 814 815 } catch (Exception e) { 816 throw new SourceException("Error getting properties", e); 817 } 818 SourceProperty[] sourcepropertiesArray = new SourceProperty[sourceproperties.size()]; 819 for (int i = 0; i<sourceproperties.size(); i++) { 820 sourcepropertiesArray[i] = (SourceProperty) sourceproperties.elementAt(i); 821 } 822 return sourcepropertiesArray; 823 } 824 825 835 public SourceProperty getSourceProperty (String namespace, String name) throws SourceException { 836 837 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 838 839 Vector propNames = new Vector (1); 840 propNames.add(new PropertyName(namespace,name)); 841 Enumeration props= null; 842 org.apache.webdav.lib.Property prop = null; 843 try { 844 Enumeration responses = this.resource.propfindMethod(0, propNames); 845 while (responses.hasMoreElements()) { 846 ResponseEntity response = (ResponseEntity) responses.nextElement(); 847 props = response.getProperties(); 848 if (props.hasMoreElements()) { 849 prop = (Property) props.nextElement(); 850 return new SourceProperty(prop.getElement()); 851 } 852 } 853 } catch (Exception e) { 854 throw new SourceException("Error getting property: "+name, e); 855 } 856 return null; 857 } 858 859 867 public void removeSourceProperty(String namespace, String name) 868 throws SourceException { 869 870 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 871 872 try { 873 this.resource.proppatchMethod(new PropertyName(namespace, name), "", false); 874 } catch (Exception e) { 875 throw new SourceException("Could not remove property ", e); 876 } 877 } 878 879 886 public void setSourceProperty(SourceProperty sourceproperty) throws SourceException { 887 888 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 889 890 try { 891 Node node = null; 892 NodeList list = sourceproperty.getValue().getChildNodes(); 893 for (int i=0; i<list.getLength(); i++) { 894 if ((list.item(i) instanceof Text && !"".equals(list.item(i).getNodeValue())) 895 || list.item(i) instanceof Element ) { 896 897 node = list.item(i); 898 break; 899 } 900 } 901 902 Properties format = new Properties (); 903 format.put(OutputKeys.METHOD, "xml"); 904 format.put(OutputKeys.OMIT_XML_DECLARATION, "yes"); 905 String prop = XMLUtils.serializeNode(node, format); 906 907 this.resource.proppatchMethod( 908 new PropertyName(sourceproperty.getNamespace(),sourceproperty.getName()), 909 prop, true); 910 911 } catch(HttpException e) { 912 final String message = 913 "Unable to set property. Server responded " + 914 e.getReasonCode() + " (" + e.getReason() + ") - " 915 + e.getMessage(); 916 getLogger().debug(message); 917 throw new SourceException("Could not set property ", e); 918 } catch (Exception e) { 919 throw new SourceException("Could not set property ", e); 920 } 921 } 922 923 926 933 936 945 947 954 public void moveTo(Source source) throws SourceException { 955 if (source instanceof WebDAVSource) { 956 initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 957 WebDAVSource destination = (WebDAVSource)source; 958 destination.initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 959 try { 960 this.resource.moveMethod(destination.resource.getHttpURL().getPath()); 961 } catch (HttpException e) { 962 throw new SourceException("Cannot move source '"+getSecureURI()+"'", e); 963 } catch (IOException e) { 964 throw new SourceException("Cannot move source '"+getSecureURI()+"'", e); 965 } 966 } else { 967 SourceUtil.move(this,source); 968 } 969 } 970 971 978 public void copyTo(Source source) throws SourceException { 979 if (source instanceof WebDAVSource) { 980 initResource(WebdavResource.BASIC, DepthSupport.DEPTH_0); 981 WebDAVSource destination = (WebDAVSource)source; 982 destination.initResource(WebdavResource.NOACTION, DepthSupport.DEPTH_0); 983 try { 984 this.resource.copyMethod(destination.resource.getHttpURL().getPath()); 985 } catch (HttpException e) { 986 throw new SourceException("Cannot copy source '"+getSecureURI()+"'", e); 987 } catch (IOException e) { 988 throw new SourceException("Cannot copy source '"+getSecureURI()+"'", e); 989 } 990 } else { 991 SourceUtil.copy(this,source); 992 } 993 } 994 } 995 | Popular Tags |