001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2.provider.webdav4; 018 019import java.io.ByteArrayOutputStream; 020import java.io.IOException; 021import java.io.OutputStream; 022import java.net.HttpURLConnection; 023import java.util.ArrayList; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.commons.vfs2.FileContentInfoFactory; 029import org.apache.commons.vfs2.FileNotFolderException; 030import org.apache.commons.vfs2.FileNotFoundException; 031import org.apache.commons.vfs2.FileObject; 032import org.apache.commons.vfs2.FileSystemException; 033import org.apache.commons.vfs2.FileType; 034import org.apache.commons.vfs2.NameScope; 035import org.apache.commons.vfs2.provider.AbstractFileName; 036import org.apache.commons.vfs2.provider.DefaultFileContent; 037import org.apache.commons.vfs2.provider.GenericURLFileName; 038import org.apache.commons.vfs2.provider.http4.Http4FileObject; 039import org.apache.commons.vfs2.util.FileObjectUtils; 040import org.apache.commons.vfs2.util.MonitorOutputStream; 041import org.apache.http.HttpEntity; 042import org.apache.http.HttpResponse; 043import org.apache.http.HttpStatus; 044import org.apache.http.client.methods.CloseableHttpResponse; 045import org.apache.http.client.methods.HttpPut; 046import org.apache.http.client.methods.HttpUriRequest; 047import org.apache.http.client.utils.DateUtils; 048import org.apache.http.entity.ByteArrayEntity; 049import org.apache.http.entity.ContentType; 050import org.apache.http.util.EntityUtils; 051import org.apache.jackrabbit.webdav.DavConstants; 052import org.apache.jackrabbit.webdav.DavException; 053import org.apache.jackrabbit.webdav.MultiStatus; 054import org.apache.jackrabbit.webdav.MultiStatusResponse; 055import org.apache.jackrabbit.webdav.client.methods.BaseDavRequest; 056import org.apache.jackrabbit.webdav.client.methods.HttpCheckin; 057import org.apache.jackrabbit.webdav.client.methods.HttpCheckout; 058import org.apache.jackrabbit.webdav.client.methods.HttpDelete; 059import org.apache.jackrabbit.webdav.client.methods.HttpMkcol; 060import org.apache.jackrabbit.webdav.client.methods.HttpMove; 061import org.apache.jackrabbit.webdav.client.methods.HttpPropfind; 062import org.apache.jackrabbit.webdav.client.methods.HttpProppatch; 063import org.apache.jackrabbit.webdav.client.methods.HttpVersionControl; 064import org.apache.jackrabbit.webdav.property.DavProperty; 065import org.apache.jackrabbit.webdav.property.DavPropertyName; 066import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; 067import org.apache.jackrabbit.webdav.property.DavPropertySet; 068import org.apache.jackrabbit.webdav.property.DefaultDavProperty; 069import org.apache.jackrabbit.webdav.version.DeltaVConstants; 070import org.apache.jackrabbit.webdav.version.VersionControlledResource; 071import org.apache.jackrabbit.webdav.xml.Namespace; 072import org.w3c.dom.Node; 073 074/** 075 * A WebDAV file. 076 * 077 * @since 2.5.0 078 */ 079public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> { 080 081 /** 082 * An OutputStream that writes to a WebDAV resource. 083 * <p> 084 * TODO - Use piped stream to avoid temporary file. 085 * </p> 086 */ 087 private class WebdavOutputStream extends MonitorOutputStream { 088 private final Webdav4FileObject file; 089 090 WebdavOutputStream(final Webdav4FileObject file) { 091 super(new ByteArrayOutputStream()); 092 this.file = file; 093 } 094 095 private boolean createVersion(final String urlStr) { 096 try { 097 final HttpVersionControl request = setupRequest(new HttpVersionControl(urlStr)); 098 // AutoClose the underlying HTTP connection which is held by the response object 099 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 100 return true; 101 } 102 } catch (final Exception ex) { 103 return false; 104 } 105 } 106 107 /** 108 * Called after this stream is closed. 109 */ 110 @Override 111 protected void onClose() throws IOException { 112 final HttpEntity entity = new ByteArrayEntity(((ByteArrayOutputStream) out).toByteArray()); 113 final GenericURLFileName fileName = (GenericURLFileName) getName(); 114 final String urlStr = toUrlString(fileName); 115 if (builder.isVersioning(getFileSystem().getFileSystemOptions())) { 116 DavPropertySet set = null; 117 boolean fileExists = true; 118 boolean isCheckedIn = true; 119 try { 120 set = getPropertyNames(fileName); 121 } catch (final FileNotFoundException fnfe) { 122 fileExists = false; 123 } 124 if (fileExists && set != null) { 125 if (set.contains(VersionControlledResource.CHECKED_OUT)) { 126 isCheckedIn = false; 127 } else if (!set.contains(VersionControlledResource.CHECKED_IN)) { 128 DavProperty<?> prop = set.get(VersionControlledResource.AUTO_VERSION); 129 if (prop != null) { 130 prop = getProperty(fileName, VersionControlledResource.AUTO_VERSION); 131 if (DeltaVConstants.XML_CHECKOUT_CHECKIN.equals(prop.getValue())) { 132 createVersion(urlStr); 133 } 134 } 135 } 136 } 137 if (fileExists && isCheckedIn) { 138 try { 139 final HttpCheckout request = setupRequest(new HttpCheckout(urlStr)); 140 // AutoClose the underlying HTTP connection which is held by the response object 141 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 142 isCheckedIn = false; 143 } 144 } catch (final FileSystemException ex) { 145 log(ex); 146 } 147 } 148 149 try { 150 final HttpPut request = new HttpPut(urlStr); 151 request.setEntity(entity); 152 setupRequest(request); 153 // AutoClose the underlying HTTP connection which is held by the response object 154 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 155 setUserName(fileName, urlStr); 156 } 157 } catch (final FileSystemException ex) { 158 if (!isCheckedIn) { 159 try { 160 final HttpCheckin request = new HttpCheckin(urlStr); 161 setupRequest(request); 162 // AutoClose the underlying HTTP connection which is held by the response object 163 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 164 isCheckedIn = true; 165 } 166 } catch (final Exception e) { 167 // Going to throw original. 168 log(e); 169 } 170 throw ex; 171 } 172 } 173 if (!fileExists) { 174 createVersion(urlStr); 175 try { 176 final DavPropertySet props = getPropertyNames(fileName); 177 isCheckedIn = !props.contains(VersionControlledResource.CHECKED_OUT); 178 } catch (final FileNotFoundException fnfe) { 179 log(fnfe); 180 } 181 } 182 if (!isCheckedIn) { 183 final HttpCheckin request = new HttpCheckin(urlStr); 184 setupRequest(request); 185 // AutoClose the underlying HTTP connection which is held by the response object 186 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 187 isCheckedIn = true; 188 } 189 } 190 } else { 191 final HttpPut request = new HttpPut(urlStr); 192 request.setEntity(entity); 193 setupRequest(request); 194 // AutoClose the underlying HTTP connection which is held by the response object 195 try (CloseableHttpResponse unused = (CloseableHttpResponse) executeRequest(request)) { 196 try { 197 setUserName(fileName, urlStr); 198 } catch (final IOException e) { 199 // Unable to set the user name. 200 log(e); 201 } 202 } 203 } 204 ((DefaultFileContent) file.getContent()).resetAttributes(); 205 } 206 207 private void setUserName(final GenericURLFileName fileName, final String urlStr) throws IOException { 208 final DavPropertySet setProperties = new DavPropertySet(); 209 final DavPropertyNameSet removeProperties = new DavPropertyNameSet(); 210 String name = builder.getCreatorName(getFileSystem().getFileSystemOptions()); 211 final String userName = fileName.getUserName(); 212 if (name == null) { 213 name = userName; 214 } else if (userName != null) { 215 final String comment = "Modified by user " + userName; 216 setProperties.add(new DefaultDavProperty<>(DeltaVConstants.COMMENT, comment)); 217 } 218 setProperties.add(new DefaultDavProperty<>(DeltaVConstants.CREATOR_DISPLAYNAME, name)); 219 final HttpProppatch request = setupRequest(new HttpProppatch(urlStr, setProperties, removeProperties)); 220 // AutoClose the underlying HTTP connection which is held by the response object 221 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 222 // TODO: workaround due to PMD violation 'Empty try body - you could rename the resource to 'ignored' 223 request.succeeded(res); 224 } 225 } 226 } 227 228 /** The character set property name. */ 229 public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create("response-charset"); 230 231 /** 232 * An empty immutable {@code Webdav4FileObject} array. 233 */ 234 private static final Webdav4FileObject[] EMPTY_ARRAY = {}; 235 236 /** The FileSystemConfigBuilder */ 237 private final Webdav4FileSystemConfigBuilder builder; 238 239 /** 240 * Constructs a new instance. 241 * 242 * @param name file name. 243 * @param fileSystem file system. 244 * @throws FileSystemException if any error occurs 245 */ 246 protected Webdav4FileObject(final AbstractFileName name, final Webdav4FileSystem fileSystem) 247 throws FileSystemException { 248 this(name, fileSystem, Webdav4FileSystemConfigBuilder.getInstance()); 249 } 250 251 /** 252 * Constructs a new instance. 253 * 254 * @param name file name. 255 * @param fileSystem file system. 256 * @param builder builds the file system configuration. 257 * @throws FileSystemException if any error occurs 258 */ 259 protected Webdav4FileObject(final AbstractFileName name, final Webdav4FileSystem fileSystem, 260 final Webdav4FileSystemConfigBuilder builder) throws FileSystemException { 261 super(name, fileSystem, builder); 262 this.builder = builder; 263 } 264 265 /** 266 * Creates this file as a folder. 267 */ 268 @Override 269 protected void doCreateFolder() throws Exception { 270 final HttpMkcol request = setupRequest(new HttpMkcol(toUrlString((GenericURLFileName) getName()))); 271 try { 272 // AutoClose the underlying HTTP connection which is held by the response object 273 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 274 // TODO: workaround due to PMD violation 'Empty try body - you could rename the resource to 'ignored' 275 request.succeeded(res); 276 } 277 } catch (final FileSystemException fse) { 278 throw new FileSystemException("vfs.provider.webdav/create-collection.error", getName(), fse); 279 } 280 } 281 282 /** 283 * Deletes the file. 284 */ 285 @Override 286 protected void doDelete() throws Exception { 287 final HttpDelete request = setupRequest(new HttpDelete(toUrlString((GenericURLFileName) getName()))); 288 // AutoClose the underlying HTTP connection which is held by the response object 289 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 290 // TODO: workaround due to PMD violation 'Empty try body - you could rename the resource to 'ignored' 291 request.succeeded(res); 292 } 293 } 294 295 /** 296 * Returns the properties of the Webdav resource. 297 */ 298 @Override 299 protected Map<String, Object> doGetAttributes() throws Exception { 300 final Map<String, Object> attributes = new HashMap<>(); 301 try { 302 final GenericURLFileName fileName = (GenericURLFileName) getName(); 303 DavPropertySet properties = getProperties(fileName, DavConstants.PROPFIND_ALL_PROP, 304 new DavPropertyNameSet(), false); 305 for (final DavProperty<?> property : properties) { 306 attributes.put(property.getName().toString(), property.getValue()); 307 } 308 properties = getPropertyNames(fileName); 309 for (DavProperty<?> property : properties) { 310 if (!attributes.containsKey(property.getName().getName())) { 311 property = getProperty(fileName, property.getName()); 312 if (property != null) { 313 final Object name = property.getName(); 314 final Object value = property.getValue(); 315 if (name != null && value != null) { 316 attributes.put(name.toString(), value); 317 } 318 } 319 } 320 } 321 return attributes; 322 } catch (final Exception e) { 323 throw new FileSystemException("vfs.provider.webdav/get-attributes.error", getName(), e); 324 } 325 } 326 327 /** 328 * Returns the size of the file content (in bytes). 329 */ 330 @Override 331 protected long doGetContentSize() throws Exception { 332 final DavProperty<?> property = getProperty((GenericURLFileName) getName(), DavConstants.PROPERTY_GETCONTENTLENGTH); 333 if (property != null) { 334 final String value = (String) property.getValue(); 335 return Long.parseLong(value); 336 } 337 return 0; 338 } 339 340 /** 341 * Returns the last modified time of this file. Is only called if {@link #doGetType} does not return 342 * {@link FileType#IMAGINARY}. 343 */ 344 @Override 345 protected long doGetLastModifiedTime() throws Exception { 346 final DavProperty<?> property = getProperty((GenericURLFileName) getName(), DavConstants.PROPERTY_GETLASTMODIFIED); 347 if (property != null) { 348 final String value = (String) property.getValue(); 349 return DateUtils.parseDate(value).getTime(); 350 } 351 return 0; 352 } 353 354 @Override 355 protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception { 356 return new WebdavOutputStream(this); 357 } 358 359 /** 360 * Determines the type of this file. Must not return null. The return value of this method is cached, so the 361 * implementation can be expensive. 362 */ 363 @Override 364 protected FileType doGetType() throws Exception { 365 try { 366 return isDirectory((GenericURLFileName) getName()) ? FileType.FOLDER : FileType.FILE; 367 } catch (final FileNotFolderException | FileNotFoundException fnfe) { 368 return FileType.IMAGINARY; 369 } 370 371 } 372 373 /** 374 * Determines if this file can be written to. Is only called if {@link #doGetType} does not return 375 * {@link FileType#IMAGINARY}. 376 * <p> 377 * This implementation always returns true. 378 * 379 * @return true if the file is writable. 380 * @throws Exception if an error occurs. 381 */ 382 @Override 383 protected boolean doIsWriteable() throws Exception { 384 return true; 385 } 386 387 /** 388 * Lists the children of the file. 389 */ 390 @Override 391 protected String[] doListChildren() throws Exception { 392 // use doListChildrenResolved for performance 393 return null; 394 } 395 396 /** 397 * Lists the children of the file. 398 */ 399 @Override 400 protected FileObject[] doListChildrenResolved() throws Exception { 401 HttpPropfind request = null; 402 try { 403 final GenericURLFileName name = (GenericURLFileName) getName(); 404 if (isDirectory(name)) { 405 final DavPropertyNameSet nameSet = new DavPropertyNameSet(); 406 nameSet.add(DavPropertyName.create(DavConstants.PROPERTY_DISPLAYNAME)); 407 408 request = new HttpPropfind(toUrlString(name), nameSet, DavConstants.DEPTH_1); 409 410 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 411 final List<Webdav4FileObject> vfs = new ArrayList<>(); 412 if (request.succeeded(res)) { 413 final MultiStatusResponse[] responses = request.getResponseBodyAsMultiStatus(res).getResponses(); 414 415 for (final MultiStatusResponse response : responses) { 416 if (isCurrentFile(response.getHref(), name)) { 417 continue; 418 } 419 final String resourceName = resourceName(response.getHref()); 420 if (!resourceName.isEmpty()) { 421 final Webdav4FileObject fo = (Webdav4FileObject) FileObjectUtils.getAbstractFileObject( 422 getFileSystem().resolveFile(getFileSystem().getFileSystemManager() 423 .resolveName(getName(), resourceName, NameScope.CHILD))); 424 vfs.add(fo); 425 } 426 } 427 } 428 return vfs.toArray(EMPTY_ARRAY); 429 } 430 } 431 throw new FileNotFolderException(getName()); 432 } catch (final FileNotFolderException fnfe) { 433 throw fnfe; 434 } catch (final DavException | IOException e) { 435 throw new FileSystemException(e.getMessage(), e); 436 } 437 } 438 439 /** 440 * Rename the file. 441 */ 442 @Override 443 protected void doRename(final FileObject newFile) throws Exception { 444 final String url = toUrlString((GenericURLFileName) getName()); 445 final String dest = toUrlString((GenericURLFileName) newFile.getName(), false); 446 final HttpMove request = setupRequest(new HttpMove(url, dest, false)); 447 // AutoClose the underlying HTTP connection which is held by the response object 448 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 449 // TODO: workaround due to PMD violation 'Empty try body - you could rename the resource to 'ignored' 450 request.succeeded(res); 451 } 452 } 453 454 /** 455 * Sets an attribute of this file. Is only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}. 456 */ 457 @Override 458 protected void doSetAttribute(final String attrName, final Object value) throws Exception { 459 try { 460 final GenericURLFileName fileName = (GenericURLFileName) getName(); 461 final String urlStr = toUrlString(fileName); 462 final DavPropertySet properties = new DavPropertySet(); 463 final DavPropertyNameSet propertyNameSet = new DavPropertyNameSet(); 464 final DavProperty<Object> property = new DefaultDavProperty<>(attrName, value, Namespace.EMPTY_NAMESPACE); 465 if (value != null) { 466 properties.add(property); 467 } else { 468 propertyNameSet.add(property.getName()); // remove property 469 } 470 471 final HttpProppatch request = setupRequest(new HttpProppatch(urlStr, properties, propertyNameSet)); 472 // AutoClose the underlying HTTP connection which is held by the response object 473 try (CloseableHttpResponse response = (CloseableHttpResponse) executeRequest(request)) { 474 if (!request.succeeded(response)) { 475 throw new FileSystemException("Property '" + attrName + "' could not be set."); 476 } 477 } 478 } catch (final FileSystemException fse) { 479 throw fse; 480 } catch (final Exception e) { 481 throw new FileSystemException("vfs.provider.webdav/set-attributes", e, getName(), attrName); 482 } 483 } 484 485 private HttpResponse executeRequest(final HttpUriRequest request) throws FileSystemException { 486 final HttpResponse response; 487 488 try { 489 response = executeHttpUriRequest(request); 490 final int status = response.getStatusLine().getStatusCode(); 491 if (status == HttpURLConnection.HTTP_NOT_FOUND || status == HttpURLConnection.HTTP_GONE) { 492 EntityUtils.consume(response.getEntity()); 493 throw new FileNotFoundException(request.getURI()); 494 } 495 496 if (request instanceof BaseDavRequest) { 497 ((BaseDavRequest) request).checkSuccess(response); 498 } 499 500 return response; 501 } catch (final FileSystemException fse) { 502 throw fse; 503 } catch (final IOException e) { 504 throw new FileSystemException(e); 505 } catch (final DavException e) { 506 throw ExceptionConverter.generate(e); 507 } 508 } 509 510 @Override 511 protected FileContentInfoFactory getFileContentInfoFactory() { 512 return new Webdav4FileContentInfoFactory(); 513 } 514 515 DavPropertySet getProperties(final GenericURLFileName name) throws FileSystemException { 516 return getProperties(name, DavConstants.PROPFIND_ALL_PROP, new DavPropertyNameSet(), false); 517 } 518 519 DavPropertySet getProperties(final GenericURLFileName name, final DavPropertyNameSet nameSet, final boolean addEncoding) 520 throws FileSystemException { 521 return getProperties(name, DavConstants.PROPFIND_BY_PROPERTY, nameSet, addEncoding); 522 } 523 524 DavPropertySet getProperties(final GenericURLFileName name, final int type, final DavPropertyNameSet nameSet, 525 final boolean addEncoding) throws FileSystemException { 526 try { 527 final String urlStr = toUrlString(name); 528 final HttpPropfind request = setupRequest(new HttpPropfind(urlStr, type, nameSet, DavConstants.DEPTH_0)); 529 try (CloseableHttpResponse res = (CloseableHttpResponse) executeRequest(request)) { 530 if (request.succeeded(res)) { 531 final MultiStatus multiStatus = request.getResponseBodyAsMultiStatus(res); 532 final MultiStatusResponse response = multiStatus.getResponses()[0]; 533 final DavPropertySet props = response.getProperties(HttpStatus.SC_OK); 534 if (addEncoding) { 535 final ContentType resContentType = ContentType.getOrDefault(res.getEntity()); 536 final DavProperty<String> prop = new DefaultDavProperty<>(RESPONSE_CHARSET, 537 resContentType.getCharset().name()); 538 props.add(prop); 539 } 540 return props; 541 } 542 return new DavPropertySet(); 543 } 544 } catch (final FileSystemException fse) { 545 throw fse; 546 } catch (final Exception e) { 547 throw new FileSystemException("vfs.provider.webdav/get-property.error", e, getName(), name, type, 548 nameSet.getContent(), addEncoding); 549 } 550 } 551 552 DavProperty<?> getProperty(final GenericURLFileName fileName, final DavPropertyName name) throws FileSystemException { 553 final DavPropertyNameSet nameSet = new DavPropertyNameSet(); 554 nameSet.add(name); 555 final DavPropertySet propertySet = getProperties(fileName, nameSet, false); 556 return propertySet.get(name); 557 } 558 559 DavProperty<?> getProperty(final GenericURLFileName fileName, final String property) throws FileSystemException { 560 return getProperty(fileName, DavPropertyName.create(property)); 561 } 562 563 DavPropertySet getPropertyNames(final GenericURLFileName name) throws FileSystemException { 564 return getProperties(name, DavConstants.PROPFIND_PROPERTY_NAMES, new DavPropertyNameSet(), false); 565 } 566 567 /** 568 * Convert the FileName to an encoded url String. 569 * 570 * @param name The FileName. 571 * @return The encoded URL String. 572 */ 573 private String hrefString(final GenericURLFileName name) { 574 try { 575 final GenericURLFileName newFile = new GenericURLFileName(getInternalURI().getScheme(), name.getHostName(), name.getPort(), name.getDefaultPort(), 576 null, null, name.getPath(), name.getType(), name.getQueryString()); 577 return newFile.getURIEncoded(getUrlCharset()); 578 } catch (final Exception e) { 579 return name.getURI(); 580 } 581 } 582 583 private boolean isCurrentFile(final String href, final GenericURLFileName fileName) { 584 String name = hrefString(fileName); 585 if (href.endsWith("/") && !name.endsWith("/")) { 586 name += "/"; 587 } 588 return href.equals(name) || href.equals(fileName.getPath()); 589 } 590 591 private boolean isDirectory(final GenericURLFileName name) throws IOException { 592 try { 593 final DavProperty<?> property = getProperty(name, DavConstants.PROPERTY_RESOURCETYPE); 594 final Node node; 595 if (property != null && (node = (Node) property.getValue()) != null) { 596 return node.getLocalName().equals(DavConstants.XML_COLLECTION); 597 } 598 return false; 599 } catch (final FileNotFoundException fse) { 600 throw new FileNotFolderException(name); 601 } 602 } 603 604 void log(final Exception ex) { 605 // TODO Consider logging 606 } 607 608 /** 609 * Returns the resource name from the path. 610 * 611 * @param path the path to the file. 612 * @return The resource name 613 */ 614 private String resourceName(String path) { 615 if (path.endsWith("/")) { 616 path = path.substring(0, path.length() - 1); 617 } 618 final int i = path.lastIndexOf("/"); 619 return i >= 0 ? path.substring(i + 1) : path; 620 } 621 622 private <T extends HttpUriRequest> T setupRequest(final T request) { 623 // NOTE: *FileSystemConfigBuilder takes care of redirect option and user agent. 624 request.addHeader("Cache-control", "no-cache"); 625 request.addHeader("Cache-store", "no-store"); 626 request.addHeader("Pragma", "no-cache"); 627 request.addHeader("Expires", "0"); 628 return request; 629 } 630 631 /** 632 * Converts the given URLFileName to an encoded URL String to internally use in real DAV operations. 633 * 634 * @param name The FileName. 635 * @return The encoded URL String. 636 */ 637 String toUrlString(final GenericURLFileName name) { 638 return toUrlString(name, true); 639 } 640 641 /** 642 * Converts the given URLFileName to an encoded URL String to internally use in real DAV operations. 643 * 644 * @param name The FileName. 645 * @param includeUserInfo true if user information should be included. 646 * @return The encoded URL String. 647 */ 648 private String toUrlString(final GenericURLFileName name, final boolean includeUserInfo) { 649 String user = null; 650 String password = null; 651 if (includeUserInfo) { 652 user = name.getUserName(); 653 password = name.getPassword(); 654 } 655 try { 656 final GenericURLFileName newFile = new Webdav4FileName(getInternalURI().getScheme(), name.getHostName(), name.getPort(), name.getDefaultPort(), 657 user, password, name.getPath(), name.getType(), name.getQueryString(), 658 builder.getAppendTrailingSlash(getFileSystem().getFileSystemOptions())); 659 return newFile.getURIEncoded(getUrlCharset()); 660 } catch (final Exception e) { 661 return name.getURI(); 662 } 663 } 664}