View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider.webdav;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.IOException;
21  import java.io.OutputStream;
22  import java.net.HttpURLConnection;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.commons.httpclient.HttpMethod;
30  import org.apache.commons.httpclient.HttpMethodBase;
31  import org.apache.commons.httpclient.HttpStatus;
32  import org.apache.commons.httpclient.URIException;
33  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
34  import org.apache.commons.httpclient.methods.RequestEntity;
35  import org.apache.commons.httpclient.params.HttpMethodParams;
36  import org.apache.commons.httpclient.util.DateUtil;
37  import org.apache.commons.vfs2.FileContentInfoFactory;
38  import org.apache.commons.vfs2.FileNotFolderException;
39  import org.apache.commons.vfs2.FileNotFoundException;
40  import org.apache.commons.vfs2.FileObject;
41  import org.apache.commons.vfs2.FileSystemException;
42  import org.apache.commons.vfs2.FileType;
43  import org.apache.commons.vfs2.NameScope;
44  import org.apache.commons.vfs2.provider.AbstractFileName;
45  import org.apache.commons.vfs2.provider.DefaultFileContent;
46  import org.apache.commons.vfs2.provider.URLFileName;
47  import org.apache.commons.vfs2.provider.http.HttpFileObject;
48  import org.apache.commons.vfs2.util.FileObjectUtils;
49  import org.apache.commons.vfs2.util.MonitorOutputStream;
50  import org.apache.jackrabbit.webdav.DavConstants;
51  import org.apache.jackrabbit.webdav.DavException;
52  import org.apache.jackrabbit.webdav.MultiStatus;
53  import org.apache.jackrabbit.webdav.MultiStatusResponse;
54  import org.apache.jackrabbit.webdav.client.methods.CheckinMethod;
55  import org.apache.jackrabbit.webdav.client.methods.CheckoutMethod;
56  import org.apache.jackrabbit.webdav.client.methods.DavMethod;
57  import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
58  import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
59  import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
60  import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
61  import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod;
62  import org.apache.jackrabbit.webdav.client.methods.PutMethod;
63  import org.apache.jackrabbit.webdav.client.methods.UncheckoutMethod;
64  import org.apache.jackrabbit.webdav.client.methods.VersionControlMethod;
65  import org.apache.jackrabbit.webdav.property.DavProperty;
66  import org.apache.jackrabbit.webdav.property.DavPropertyName;
67  import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
68  import org.apache.jackrabbit.webdav.property.DavPropertySet;
69  import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
70  import org.apache.jackrabbit.webdav.version.DeltaVConstants;
71  import org.apache.jackrabbit.webdav.version.VersionControlledResource;
72  import org.apache.jackrabbit.webdav.xml.Namespace;
73  import org.w3c.dom.Node;
74  
75  /**
76   * A WebDAV file.
77   *
78   * @since 2.0
79   */
80  public class WebdavFileObject extends HttpFileObject<WebdavFileSystem>
81  {
82      /**
83       * An OutputStream that writes to a Webdav resource.
84       * <p>
85       * TODO - Use piped stream to avoid temporary file.
86       */
87      private class WebdavOutputStream extends MonitorOutputStream
88      {
89          private final WebdavFileObject file;
90  
91          public WebdavOutputStream(final WebdavFileObject file)
92          {
93              super(new ByteArrayOutputStream());
94              this.file = file;
95          }
96  
97          private boolean createVersion(final String urlStr)
98          {
99              try
100             {
101                 final VersionControlMethod method = new VersionControlMethod(urlStr);
102                 setupMethod(method);
103                 execute(method);
104                 return true;
105             }
106             catch (final Exception ex)
107             {
108                 return false;
109             }
110         }
111 
112         /**
113          * Called after this stream is closed.
114          */
115         @Override
116         protected void onClose() throws IOException
117         {
118             final RequestEntity entity = new ByteArrayRequestEntity(((ByteArrayOutputStream) out).toByteArray());
119             final URLFileName fileName = (URLFileName) getName();
120             final String urlStr = toUrlString(fileName);
121             if (builder.isVersioning(getFileSystem().getFileSystemOptions()))
122             {
123                 DavPropertySet set = null;
124                 boolean fileExists = true;
125                 boolean isCheckedIn = true;
126                 try
127                 {
128                     set = getPropertyNames(fileName);
129                 }
130                 catch (final FileNotFoundException fnfe)
131                 {
132                     fileExists = false;
133                 }
134                 if (fileExists && set != null)
135                 {
136                     if (set.contains(VersionControlledResource.CHECKED_OUT))
137                     {
138                         isCheckedIn = false;
139                     }
140                     else if (!set.contains(VersionControlledResource.CHECKED_IN))
141                     {
142                         DavProperty prop = set.get(VersionControlledResource.AUTO_VERSION);
143                         if (prop != null)
144                         {
145                             prop = getProperty(fileName, VersionControlledResource.AUTO_VERSION);
146                             if (DeltaVConstants.XML_CHECKOUT_CHECKIN.equals(prop.getValue()))
147                             {
148                                 createVersion(urlStr);
149                             }
150                         }
151                     }
152                 }
153                 if (fileExists && isCheckedIn)
154                 {
155                     try
156                     {
157                         final CheckoutMethod checkout = new CheckoutMethod(urlStr);
158                         setupMethod(checkout);
159                         execute(checkout);
160                         isCheckedIn = false;
161                     }
162                     catch (final FileSystemException ex)
163                     {
164                         // Ignore the exception checking out.
165                     }
166                 }
167 
168                 try
169                 {
170                     final PutMethod method = new PutMethod(urlStr);
171                     method.setRequestEntity(entity);
172                     setupMethod(method);
173                     execute(method);
174                     setUserName(fileName, urlStr);
175                 }
176                 catch (final FileSystemException ex)
177                 {
178                     if (!isCheckedIn)
179                     {
180                         try
181                         {
182                             final UncheckoutMethod method = new UncheckoutMethod(urlStr);
183                             setupMethod(method);
184                             execute(method);
185                             isCheckedIn = true;
186                         }
187                         catch (final Exception e)
188                         {
189                             // Ignore the exception. Going to throw original.
190                         }
191                         throw ex;
192                     }
193                 }
194                 if (!fileExists)
195                 {
196                     createVersion(urlStr);
197                     try
198                     {
199                         final DavPropertySet props = getPropertyNames(fileName);
200                         isCheckedIn = !props.contains(VersionControlledResource.CHECKED_OUT);
201                     }
202                     catch (final FileNotFoundException fnfe)
203                     {
204                         // Ignore the error
205                     }
206                 }
207                 if (!isCheckedIn)
208                 {
209                   final CheckinMethod checkin = new CheckinMethod(urlStr);
210                   setupMethod(checkin);
211                   execute(checkin);
212                 }
213             }
214             else
215             {
216                 final PutMethod method = new PutMethod(urlStr);
217                 method.setRequestEntity(entity);
218                 setupMethod(method);
219                 execute(method);
220                 try
221                 {
222                     setUserName(fileName, urlStr);
223                 }
224                 catch (final IOException e)
225                 {
226                     // Ignore the exception if unable to set the user name.
227                 }
228             }
229             ((DefaultFileContent) this.file.getContent()).resetAttributes();
230         }
231 
232         private void setUserName(final URLFileName fileName, final String urlStr)
233                 throws IOException
234         {
235             final List<DefaultDavProperty> list = new ArrayList<DefaultDavProperty>();
236             String name = builder.getCreatorName(getFileSystem().getFileSystemOptions());
237             final String userName = fileName.getUserName();
238             if (name == null)
239             {
240                 name = userName;
241             }
242             else
243             {
244                 if (userName != null)
245                 {
246                     final String comment = "Modified by user " + userName;
247                     list.add(new DefaultDavProperty(DeltaVConstants.COMMENT, comment));
248                 }
249             }
250             list.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, name));
251             final PropPatchMethod method = new PropPatchMethod(urlStr, list);
252             setupMethod(method);
253             execute(method);
254         }
255     }
256 
257     /** The character set property name. */
258     public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create(
259             "response-charset");
260 
261     /** The FileSystemConfigBuilder */
262     private final WebdavFileSystemConfigBuilder builder;
263 
264     private final WebdavFileSystem fileSystem;
265 
266     protected WebdavFileObject(final AbstractFileName name, final WebdavFileSystem fileSystem)
267     {
268         super(name, fileSystem, WebdavFileSystemConfigBuilder.getInstance());
269         this.fileSystem = fileSystem;
270         builder = (WebdavFileSystemConfigBuilder) WebdavFileSystemConfigBuilder.getInstance();
271     }
272 
273     protected void configureMethod(final HttpMethodBase httpMethod)
274     {
275         httpMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, WebdavMethodRetryHandler.getInstance());
276     }
277 
278     /**
279      * Creates this file as a folder.
280      */
281     @Override
282     protected void doCreateFolder() throws Exception
283     {
284         final DavMethod method = new MkColMethod(toUrlString((URLFileName) getName()));
285         setupMethod(method);
286         try
287         {
288             execute(method);
289         }
290         catch (final FileSystemException fse)
291         {
292             throw new FileSystemException("vfs.provider.webdav/create-collection.error", getName(),
293                     fse);
294         }
295     }
296 
297     /**
298      * Deletes the file.
299      */
300     @Override
301     protected void doDelete() throws Exception
302     {
303         final DavMethod method = new DeleteMethod(toUrlString((URLFileName) getName()));
304         setupMethod(method);
305         execute(method);
306     }
307 
308     /**
309      * Returns the properties of the Webdav resource.
310      */
311     @Override
312     protected Map<String, Object> doGetAttributes() throws Exception
313     {
314         final Map<String, Object> attributes = new HashMap<String, Object>();
315         try
316         {
317             final URLFileName fileName = (URLFileName) getName();
318             DavPropertySet properties = getProperties(fileName, DavConstants.PROPFIND_ALL_PROP,
319                     new DavPropertyNameSet(), false);
320             @SuppressWarnings("unchecked") // iterator() is documented to return DavProperty instances
321             final
322             Iterator<DavProperty> iter = properties.iterator();
323             while (iter.hasNext())
324             {
325                 final DavProperty property = iter.next();
326                 attributes.put(property.getName().toString(), property.getValue());
327             }
328             properties = getPropertyNames(fileName);
329             @SuppressWarnings("unchecked") // iterator() is documented to return DavProperty instances
330             final
331             Iterator<DavProperty> iter2 = properties.iterator();
332             while (iter2.hasNext())
333             {
334                 DavProperty property = iter2.next();
335                 if (!attributes.containsKey(property.getName().getName()))
336                 {
337                     property = getProperty(fileName, property.getName());
338                     if (property != null)
339                     {
340                         final Object name = property.getName();
341                         final Object value = property.getValue();
342                         if (name != null && value != null)
343                         {
344                             attributes.put(name.toString(), value);
345                         }
346                     }
347                 }
348             }
349             return attributes;
350         }
351         catch (final Exception e)
352         {
353             throw new FileSystemException("vfs.provider.webdav/get-attributes.error", getName(), e);
354         }
355     }
356 
357     /**
358      * Returns the size of the file content (in bytes).
359      */
360     @Override
361     protected long doGetContentSize() throws Exception
362     {
363         final DavProperty property = getProperty((URLFileName) getName(),
364                 DavConstants.PROPERTY_GETCONTENTLENGTH);
365         if (property != null)
366         {
367             final String value = (String) property.getValue();
368             return Long.parseLong(value);
369         }
370         return 0;
371     }
372 
373     /**
374      * Returns the last modified time of this file.  Is only called if
375      * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
376      */
377     @Override
378     protected long doGetLastModifiedTime() throws Exception
379     {
380         final DavProperty property = getProperty((URLFileName) getName(),
381                 DavConstants.PROPERTY_GETLASTMODIFIED);
382         if (property != null)
383         {
384             final String value = (String) property.getValue();
385             return DateUtil.parseDate(value).getTime();
386         }
387         return 0;
388     }
389 
390     @Override
391     protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception
392     {
393         return new WebdavOutputStream(this);
394     }
395 
396     /**
397      * Determines the type of this file.  Must not return null.  The return
398      * value of this method is cached, so the implementation can be expensive.
399      */
400     @Override
401     protected FileType doGetType() throws Exception
402     {
403         try
404         {
405             return isDirectory((URLFileName) getName()) ? FileType.FOLDER : FileType.FILE;
406         }
407         catch (final FileNotFolderException fnfe)
408         {
409             return FileType.IMAGINARY;
410         }
411         catch (final FileNotFoundException fnfe)
412         {
413             return FileType.IMAGINARY;
414         }
415 
416     }
417 
418     /**
419      * Determines if this file can be written to.  Is only called if
420      * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
421      * <p>
422      * This implementation always returns true.
423      *
424      * @return true if the file is writable.
425      * @throws Exception if an error occurs.
426      */
427     @Override
428     protected boolean doIsWriteable() throws Exception
429     {
430         return true;
431     }
432 
433     /**
434      * Lists the children of the file.
435      */
436     @Override
437     protected String[] doListChildren() throws Exception
438     {
439         // use doListChildrenResolved for performance
440         return null;
441     }
442 
443     /**
444      * Lists the children of the file.
445      */
446     @Override
447     protected FileObject[] doListChildrenResolved() throws Exception
448     {
449         PropFindMethod method = null;
450         try
451         {
452             final URLFileName name = (URLFileName) getName();
453             if (isDirectory(name))
454             {
455                 final DavPropertyNameSet nameSet = new DavPropertyNameSet();
456                 nameSet.add(DavPropertyName.create(DavConstants.PROPERTY_DISPLAYNAME));
457 
458                 method = new PropFindMethod(toUrlString(name), nameSet,
459                         DavConstants.DEPTH_1);
460 
461                 execute(method);
462                 final List<WebdavFileObject> vfs = new ArrayList<WebdavFileObject>();
463                 if (method.succeeded())
464                 {
465                     final MultiStatusResponse[] responses =
466                             method.getResponseBodyAsMultiStatus().getResponses();
467 
468                     for (final MultiStatusResponse response : responses)
469                     {
470                         if (isCurrentFile(response.getHref(), name))
471                         {
472                             continue;
473                         }
474                         final String resourceName = resourceName(response.getHref());
475                         if (resourceName != null && resourceName.length() > 0)
476                         {
477                             final WebdavFileObject fo = (WebdavFileObject) FileObjectUtils.
478                                     getAbstractFileObject(getFileSystem().resolveFile(
479                                             getFileSystem().getFileSystemManager().
480                                                     resolveName(getName(), resourceName,
481                                                     NameScope.CHILD)));
482                             vfs.add(fo);
483                         }
484                     }
485                 }
486                 return vfs.toArray(new WebdavFileObject[vfs.size()]);
487             }
488             throw new FileNotFolderException(getName());
489         }
490         catch (final FileNotFolderException fnfe)
491         {
492             throw fnfe;
493         }
494         catch (final DavException e)
495         {
496             throw new FileSystemException(e.getMessage(), e);
497         }
498         catch (final IOException e)
499         {
500             throw new FileSystemException(e.getMessage(), e);
501         }
502         finally
503         {
504             if (method != null)
505             {
506                 method.releaseConnection();
507             }
508         }
509     }
510 
511     /**
512      * Rename the file.
513      */
514     @Override
515     protected void doRename(final FileObject newFile) throws Exception
516     {
517         final String url = encodePath(toUrlString((URLFileName) getName()));
518         final String dest = toUrlString((URLFileName) newFile.getName(), false);
519         final DavMethod method = new MoveMethod(url, dest, false);
520         setupMethod(method);
521         execute(method);
522     }
523 
524     /**
525      * Sets an attribute of this file.  Is only called if {@link #doGetType}
526      * does not return {@link FileType#IMAGINARY}.
527      */
528     @Override
529     protected void doSetAttribute(final String attrName, final Object value)
530         throws Exception
531     {
532         try
533         {
534             final URLFileName fileName = (URLFileName) getName();
535             final String urlStr = toUrlString(fileName);
536             final DavPropertySet properties = new DavPropertySet();
537             final DavPropertyNameSet propertyNameSet = new DavPropertyNameSet();
538             final DavProperty property = new DefaultDavProperty(attrName, value, Namespace.EMPTY_NAMESPACE);
539             if (value != null)
540             {
541                 properties.add(property);
542             }
543             else
544             {
545                 propertyNameSet.add(property.getName()); // remove property
546             }
547 
548             final PropPatchMethod method = new PropPatchMethod(urlStr, properties, propertyNameSet);
549             setupMethod(method);
550             execute(method);
551             if (!method.succeeded())
552             {
553                 throw new FileSystemException("Property '" + attrName + "' could not be set.");
554             }
555         }
556         catch (final FileSystemException fse)
557         {
558             throw fse;
559         }
560         catch (final Exception e)
561         {
562             throw new FileSystemException("vfs.provider.webdav/set-attributes", e, getName(), attrName);
563         }
564     }
565 
566     /**
567      * Execute a 'Workspace' operation.
568      *
569      * @param method The DavMethod to invoke.
570      * @throws FileSystemException If an error occurs.
571      */
572     private void execute(final DavMethod method) throws FileSystemException
573     {
574         try
575         {
576             final int status = fileSystem.getClient().executeMethod(method);
577             if (status == HttpURLConnection.HTTP_NOT_FOUND
578                     || status == HttpURLConnection.HTTP_GONE)
579             {
580                 throw new FileNotFoundException(method.getURI());
581             }
582             method.checkSuccess();
583         }
584         catch (final FileSystemException fse)
585         {
586             throw fse;
587         }
588         catch (final IOException e)
589         {
590             throw new FileSystemException(e);
591         }
592         catch (final DavException e)
593         {
594             throw ExceptionConverter.generate(e);
595         }
596         finally
597         {
598             if (method != null)
599             {
600                 method.releaseConnection();
601             }
602         }
603     }
604 
605     @Override
606     protected FileContentInfoFactory getFileContentInfoFactory()
607     {
608         return new WebdavFileContentInfoFactory();
609     }
610 
611     DavPropertySet getProperties(final URLFileName name) throws FileSystemException
612     {
613         return getProperties(name, DavConstants.PROPFIND_ALL_PROP, new DavPropertyNameSet(),
614                 false);
615     }
616 
617     DavPropertySet getProperties(final URLFileName name, final DavPropertyNameSet nameSet, final boolean addEncoding)
618             throws FileSystemException
619     {
620         return getProperties(name, DavConstants.PROPFIND_BY_PROPERTY, nameSet, addEncoding);
621     }
622 
623     DavPropertySet getProperties(final URLFileName name, final int type, final DavPropertyNameSet nameSet,
624                                  final boolean addEncoding)
625             throws FileSystemException
626     {
627         try
628         {
629             final String urlStr = toUrlString(name);
630             final PropFindMethod method = new PropFindMethod(urlStr, type, nameSet, DavConstants.DEPTH_0);
631             setupMethod(method);
632             execute(method);
633             if (method.succeeded())
634             {
635                 final MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
636                 final MultiStatusResponse response = multiStatus.getResponses()[0];
637                 final DavPropertySet props = response.getProperties(HttpStatus.SC_OK);
638                 if (addEncoding)
639                 {
640                     final DavProperty prop = new DefaultDavProperty(RESPONSE_CHARSET,
641                             method.getResponseCharSet());
642                     props.add(prop);
643                 }
644                 return props;
645             }
646             return new DavPropertySet();
647         }
648         catch (final FileSystemException fse)
649         {
650             throw fse;
651         }
652         catch (final Exception e)
653         {
654             throw new FileSystemException("vfs.provider.webdav/get-property.error", e, getName(), name, type,
655                     nameSet.getContent(), addEncoding);
656         }
657     }
658 
659     DavProperty getProperty(final URLFileName fileName, final DavPropertyName name)
660             throws FileSystemException
661     {
662         final DavPropertyNameSet nameSet = new DavPropertyNameSet();
663         nameSet.add(name);
664         final DavPropertySet propertySet = getProperties(fileName, nameSet, false);
665         return propertySet.get(name);
666     }
667 
668     DavProperty getProperty(final URLFileName fileName, final String property)
669             throws FileSystemException
670     {
671         return getProperty(fileName, DavPropertyName.create(property));
672     }
673 
674 
675     DavPropertySet getPropertyNames(final URLFileName name) throws FileSystemException
676     {
677         return getProperties(name, DavConstants.PROPFIND_PROPERTY_NAMES,
678                 new DavPropertyNameSet(), false);
679     }
680 
681     /**
682      * Convert the FileName to an encoded url String.
683      *
684      * @param name The FileName.
685      * @return The encoded URL String.
686      */
687     private String hrefString(final URLFileName name)
688     {
689         final URLFileName newFile = new URLFileName("http", name.getHostName(), name.getPort(),
690                 name.getDefaultPort(), null, null,
691                 name.getPath(), name.getType(), name.getQueryString());
692         try
693         {
694             return newFile.getURIEncoded(this.getUrlCharset());
695         }
696         catch (final Exception e)
697         {
698             return name.getURI();
699         }
700     }
701 
702     private boolean isCurrentFile(final String href, final URLFileName fileName)
703     {
704         String name = hrefString(fileName);
705         if (href.endsWith("/") && !name.endsWith("/"))
706         {
707             name += "/";
708         }
709         return href.equals(name) || href.equals(fileName.getPath());
710     }
711 
712     private boolean isDirectory(final URLFileName name) throws IOException
713     {
714         try
715         {
716             final DavProperty property = getProperty(name, DavConstants.PROPERTY_RESOURCETYPE);
717             Node node;
718             if (property != null && (node = (Node) property.getValue()) != null)
719             {
720                 return node.getLocalName().equals(DavConstants.XML_COLLECTION);
721             }
722             else
723             {
724                 return false;
725             }
726         }
727         catch (final FileNotFoundException fse)
728         {
729             throw new FileNotFolderException(name);
730         }
731     }
732 
733     /**
734      * Returns the resource name from the path.
735      *
736      * @param path the path to the file.
737      * @return The resource name
738      */
739     private String resourceName(String path)
740     {
741         if (path.endsWith("/"))
742         {
743             path = path.substring(0, path.length() - 1);
744         }
745         final int i = path.lastIndexOf("/");
746         return i >= 0 ? path.substring(i + 1) : path;
747     }
748 
749     /**
750      * Prepares a Method object.
751      *
752      * @param method the HttpMethod.
753      * @throws FileSystemException if an error occurs encoding the uri.
754      * @throws URIException        if the URI is in error.
755      */
756     @Override
757     protected void setupMethod(final HttpMethod method) throws FileSystemException, URIException
758     {
759         final String pathEncoded = ((URLFileName) getName()).getPathQueryEncoded(this.getUrlCharset());
760         method.setPath(pathEncoded);
761         method.setFollowRedirects(this.getFollowRedirect());
762         method.setRequestHeader("User-Agent", "Jakarta-Commons-VFS");
763         method.addRequestHeader("Cache-control", "no-cache");
764         method.addRequestHeader("Cache-store", "no-store");
765         method.addRequestHeader("Pragma", "no-cache");
766         method.addRequestHeader("Expires", "0");
767     }
768 
769     private String toUrlString(final URLFileName name)
770     {
771         return toUrlString(name, true);
772     }
773 
774     /**
775      * Converts the given URLFileName to an encoded URL String.
776      *
777      * @param name The FileName.
778      * @param includeUserInfo true if user information should be included.
779      * @return The encoded URL String.
780      */
781     private String toUrlString(final URLFileName name, final boolean includeUserInfo)
782     {
783         String user = null;
784         String password = null;
785         if (includeUserInfo)
786         {
787             user = name.getUserName();
788             password = name.getPassword();
789         }
790         final URLFileName newFile = new URLFileName("http", name.getHostName(), name.getPort(),
791                 name.getDefaultPort(), user, password,
792                 name.getPath(), name.getType(), name.getQueryString());
793         try
794         {
795             return newFile.getURIEncoded(this.getUrlCharset());
796         }
797         catch (final Exception e)
798         {
799             return name.getURI();
800         }
801     }
802 }