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.webdav4;
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.List;
26  import java.util.Map;
27  
28  import org.apache.commons.vfs2.FileContentInfoFactory;
29  import org.apache.commons.vfs2.FileNotFolderException;
30  import org.apache.commons.vfs2.FileNotFoundException;
31  import org.apache.commons.vfs2.FileObject;
32  import org.apache.commons.vfs2.FileSystemException;
33  import org.apache.commons.vfs2.FileType;
34  import org.apache.commons.vfs2.NameScope;
35  import org.apache.commons.vfs2.provider.AbstractFileName;
36  import org.apache.commons.vfs2.provider.DefaultFileContent;
37  import org.apache.commons.vfs2.provider.GenericURLFileName;
38  import org.apache.commons.vfs2.provider.http4.Http4FileObject;
39  import org.apache.commons.vfs2.util.FileObjectUtils;
40  import org.apache.commons.vfs2.util.MonitorOutputStream;
41  import org.apache.commons.vfs2.util.URIUtils;
42  import org.apache.http.HttpEntity;
43  import org.apache.http.HttpResponse;
44  import org.apache.http.HttpStatus;
45  import org.apache.http.client.methods.HttpPut;
46  import org.apache.http.client.methods.HttpRequestBase;
47  import org.apache.http.client.methods.HttpUriRequest;
48  import org.apache.http.client.utils.DateUtils;
49  import org.apache.http.entity.ByteArrayEntity;
50  import org.apache.http.entity.ContentType;
51  import org.apache.jackrabbit.webdav.DavConstants;
52  import org.apache.jackrabbit.webdav.DavException;
53  import org.apache.jackrabbit.webdav.MultiStatus;
54  import org.apache.jackrabbit.webdav.MultiStatusResponse;
55  import org.apache.jackrabbit.webdav.client.methods.BaseDavRequest;
56  import org.apache.jackrabbit.webdav.client.methods.HttpCheckin;
57  import org.apache.jackrabbit.webdav.client.methods.HttpCheckout;
58  import org.apache.jackrabbit.webdav.client.methods.HttpDelete;
59  import org.apache.jackrabbit.webdav.client.methods.HttpMkcol;
60  import org.apache.jackrabbit.webdav.client.methods.HttpMove;
61  import org.apache.jackrabbit.webdav.client.methods.HttpPropfind;
62  import org.apache.jackrabbit.webdav.client.methods.HttpProppatch;
63  import org.apache.jackrabbit.webdav.client.methods.HttpVersionControl;
64  import org.apache.jackrabbit.webdav.property.DavProperty;
65  import org.apache.jackrabbit.webdav.property.DavPropertyIterator;
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.5.0
79   */
80  public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> {
81  
82      /**
83       * An empty immutable {@code Webdav4FileObject} array.
84       */
85      private static final Webdav4FileObject/Webdav4FileObject.html#Webdav4FileObject">Webdav4FileObject[] EMPTY_ARRAY = new Webdav4FileObject[0];
86  
87      /**
88       * An OutputStream that writes to a Webdav resource.
89       * <p>
90       * TODO - Use piped stream to avoid temporary file.
91       */
92      private class WebdavOutputStream extends MonitorOutputStream {
93          private final Webdav4FileObject file;
94  
95          public WebdavOutputStream(final Webdav4FileObject file) {
96              super(new ByteArrayOutputStream());
97              this.file = file;
98          }
99  
100         private boolean createVersion(final String urlStr) {
101             try {
102                 final HttpVersionControl request = new HttpVersionControl(urlStr);
103                 setupRequest(request);
104                 executeRequest(request);
105                 return true;
106             } catch (final Exception ex) {
107                 return false;
108             }
109         }
110 
111         /**
112          * Called after this stream is closed.
113          */
114         @Override
115         protected void onClose() throws IOException {
116             final HttpEntity entity = new ByteArrayEntity(((ByteArrayOutputStream) out).toByteArray());
117             final GenericURLFileName/../org/apache/commons/vfs2/provider/GenericURLFileName.html#GenericURLFileName">GenericURLFileName fileName = (GenericURLFileName) getName();
118             final String urlStr = toUrlString(fileName);
119             if (builder.isVersioning(getFileSystem().getFileSystemOptions())) {
120                 DavPropertySet set = null;
121                 boolean fileExists = true;
122                 boolean isCheckedIn = true;
123                 try {
124                     set = getPropertyNames(fileName);
125                 } catch (final FileNotFoundException fnfe) {
126                     fileExists = false;
127                 }
128                 if (fileExists && set != null) {
129                     if (set.contains(VersionControlledResource.CHECKED_OUT)) {
130                         isCheckedIn = false;
131                     } else if (!set.contains(VersionControlledResource.CHECKED_IN)) {
132                         DavProperty<?> prop = set.get(VersionControlledResource.AUTO_VERSION);
133                         if (prop != null) {
134                             prop = getProperty(fileName, VersionControlledResource.AUTO_VERSION);
135                             if (DeltaVConstants.XML_CHECKOUT_CHECKIN.equals(prop.getValue())) {
136                                 createVersion(urlStr);
137                             }
138                         }
139                     }
140                 }
141                 if (fileExists && isCheckedIn) {
142                     try {
143                         final HttpCheckout request = new HttpCheckout(urlStr);
144                         setupRequest(request);
145                         executeRequest(request);
146                         isCheckedIn = false;
147                     } catch (final FileSystemException ex) {
148                         log(ex);
149                     }
150                 }
151 
152                 try {
153                     final HttpPut request = new HttpPut(urlStr);
154                     request.setEntity(entity);
155                     setupRequest(request);
156                     executeRequest(request);
157                     setUserName(fileName, urlStr);
158                 } catch (final FileSystemException ex) {
159                     if (!isCheckedIn) {
160                         try {
161                             final HttpCheckin request = new HttpCheckin(urlStr);
162                             setupRequest(request);
163                             executeRequest(request);
164                             isCheckedIn = true;
165                         } catch (final Exception e) {
166                             // Going to throw original.
167                             log(e);
168                         }
169                         throw ex;
170                     }
171                 }
172                 if (!fileExists) {
173                     createVersion(urlStr);
174                     try {
175                         final DavPropertySet props = getPropertyNames(fileName);
176                         isCheckedIn = !props.contains(VersionControlledResource.CHECKED_OUT);
177                     } catch (final FileNotFoundException fnfe) {
178                         log(fnfe);
179                     }
180                 }
181                 if (!isCheckedIn) {
182                     final HttpCheckin request = new HttpCheckin(urlStr);
183                     setupRequest(request);
184                     executeRequest(request);
185                 }
186             } else {
187                 final HttpPut request = new HttpPut(urlStr);
188                 request.setEntity(entity);
189                 setupRequest(request);
190                 executeRequest(request);
191                 try {
192                     setUserName(fileName, urlStr);
193                 } catch (final IOException e) {
194                     // Unable to set the user name.
195                     log(e);
196                 }
197             }
198             ((DefaultFileContent) this.file.getContent()).resetAttributes();
199         }
200 
201         private void setUserName(final GenericURLFileName fileName, final String urlStr) throws IOException {
202             final DavPropertySet setProperties = new DavPropertySet();
203             final DavPropertyNameSet removeProperties = new DavPropertyNameSet();
204             String name = builder.getCreatorName(getFileSystem().getFileSystemOptions());
205             final String userName = fileName.getUserName();
206             if (name == null) {
207                 name = userName;
208             } else if (userName != null) {
209                 final String comment = "Modified by user " + userName;
210                 setProperties.add(new DefaultDavProperty<>(DeltaVConstants.COMMENT, comment));
211             }
212             setProperties.add(new DefaultDavProperty<>(DeltaVConstants.CREATOR_DISPLAYNAME, name));
213             final HttpProppatch request = new HttpProppatch(urlStr, setProperties, removeProperties);
214             setupRequest(request);
215             executeRequest(request);
216         }
217     }
218 
219     /** The character set property name. */
220     public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create("response-charset");
221 
222     /** The FileSystemConfigBuilder */
223     private final Webdav4FileSystemConfigBuilder builder;
224 
225 
226     protected Webdav4FileObject(final AbstractFileName name, final Webdav4FileSystem fileSystem)
227             throws FileSystemException {
228         this(name, fileSystem, Webdav4FileSystemConfigBuilder.getInstance());
229     }
230 
231     void log(Exception ex) {
232         // TODO Consider logging
233     }
234 
235     protected Webdav4FileObject(final AbstractFileName name, final Webdav4FileSystem fileSystem,
236             final Webdav4FileSystemConfigBuilder builder) throws FileSystemException {
237         super(name, fileSystem, builder);
238         this.builder = builder;
239     }
240 
241     /**
242      * Creates this file as a folder.
243      */
244     @Override
245     protected void doCreateFolder() throws Exception {
246         final HttpMkcol request = new HttpMkcol(toUrlString((GenericURLFileName) getName()));
247         setupRequest(request);
248         try {
249             executeRequest(request);
250         } catch (final FileSystemException fse) {
251             throw new FileSystemException("vfs.provider.webdav/create-collection.error", getName(), fse);
252         }
253     }
254 
255     /**
256      * Deletes the file.
257      */
258     @Override
259     protected void doDelete() throws Exception {
260         final HttpDelete request = new HttpDelete(toUrlString((GenericURLFileName) getName()));
261         setupRequest(request);
262         executeRequest(request);
263     }
264 
265     /**
266      * Returns the properties of the Webdav resource.
267      */
268     @Override
269     protected Map<String, Object> doGetAttributes() throws Exception {
270         final Map<String, Object> attributes = new HashMap<>();
271         try {
272             final GenericURLFileName/../org/apache/commons/vfs2/provider/GenericURLFileName.html#GenericURLFileName">GenericURLFileName fileName = (GenericURLFileName) getName();
273             DavPropertySet properties = getProperties(fileName, DavConstants.PROPFIND_ALL_PROP,
274                     new DavPropertyNameSet(), false);
275             final DavPropertyIterator iter = properties.iterator();
276             while (iter.hasNext()) {
277                 final DavProperty<?> property = iter.nextProperty();
278                 attributes.put(property.getName().toString(), property.getValue());
279             }
280             properties = getPropertyNames(fileName);
281             final DavPropertyIterator iter2 = properties.iterator();
282             while (iter2.hasNext()) {
283                 DavProperty<?> property = iter2.nextProperty();
284                 if (!attributes.containsKey(property.getName().getName())) {
285                     property = getProperty(fileName, property.getName());
286                     if (property != null) {
287                         final Object name = property.getName();
288                         final Object value = property.getValue();
289                         if (name != null && value != null) {
290                             attributes.put(name.toString(), value);
291                         }
292                     }
293                 }
294             }
295             return attributes;
296         } catch (final Exception e) {
297             throw new FileSystemException("vfs.provider.webdav/get-attributes.error", getName(), e);
298         }
299     }
300 
301     /**
302      * Returns the size of the file content (in bytes).
303      */
304     @Override
305     protected long doGetContentSize() throws Exception {
306         final DavProperty<?> property = getProperty((GenericURLFileName) getName(), DavConstants.PROPERTY_GETCONTENTLENGTH);
307         if (property != null) {
308             final String value = (String) property.getValue();
309             return Long.parseLong(value);
310         }
311         return 0;
312     }
313 
314     /**
315      * Returns the last modified time of this file. Is only called if {@link #doGetType} does not return
316      * {@link FileType#IMAGINARY}.
317      */
318     @Override
319     protected long doGetLastModifiedTime() throws Exception {
320         final DavProperty<?> property = getProperty((GenericURLFileName) getName(), DavConstants.PROPERTY_GETLASTMODIFIED);
321         if (property != null) {
322             final String value = (String) property.getValue();
323             return DateUtils.parseDate(value).getTime();
324         }
325         return 0;
326     }
327 
328     @Override
329     protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
330         return new WebdavOutputStream(this);
331     }
332 
333     /**
334      * Determines the type of this file. Must not return null. The return value of this method is cached, so the
335      * implementation can be expensive.
336      */
337     @Override
338     protected FileType doGetType() throws Exception {
339         try {
340             return isDirectory((GenericURLFileName) getName()) ? FileType.FOLDER : FileType.FILE;
341         } catch (final FileNotFolderException | FileNotFoundException fnfe) {
342             return FileType.IMAGINARY;
343         }
344 
345     }
346 
347     /**
348      * Determines if this file can be written to. Is only called if {@link #doGetType} does not return
349      * {@link FileType#IMAGINARY}.
350      * <p>
351      * This implementation always returns true.
352      *
353      * @return true if the file is writable.
354      * @throws Exception if an error occurs.
355      */
356     @Override
357     protected boolean doIsWriteable() throws Exception {
358         return true;
359     }
360 
361     /**
362      * Lists the children of the file.
363      */
364     @Override
365     protected String[] doListChildren() throws Exception {
366         // use doListChildrenResolved for performance
367         return null;
368     }
369 
370     /**
371      * Lists the children of the file.
372      */
373     @Override
374     protected FileObject[] doListChildrenResolved() throws Exception {
375         HttpPropfind request = null;
376         try {
377             final GenericURLFileName./../../org/apache/commons/vfs2/provider/GenericURLFileName.html#GenericURLFileName">GenericURLFileName name = (GenericURLFileName) getName();
378             if (isDirectory(name)) {
379                 final DavPropertyNameSet nameSet = new DavPropertyNameSet();
380                 nameSet.add(DavPropertyName.create(DavConstants.PROPERTY_DISPLAYNAME));
381 
382                 request = new HttpPropfind(toUrlString(name), nameSet, DavConstants.DEPTH_1);
383 
384                 final HttpResponse res = executeRequest(request);
385                 final List<Webdav4FileObject> vfs = new ArrayList<>();
386                 if (request.succeeded(res)) {
387                     final MultiStatusResponse[] responses = request.getResponseBodyAsMultiStatus(res).getResponses();
388 
389                     for (final MultiStatusResponse response : responses) {
390                         if (isCurrentFile(response.getHref(), name)) {
391                             continue;
392                         }
393                         final String resourceName = resourceName(response.getHref());
394                         if (!resourceName.isEmpty()) {
395                             final Webdav4FileObject./../../../org/apache/commons/vfs2/provider/webdav4/Webdav4FileObject.html#Webdav4FileObject">Webdav4FileObject fo = (Webdav4FileObject) FileObjectUtils.getAbstractFileObject(
396                                     getFileSystem().resolveFile(getFileSystem().getFileSystemManager()
397                                             .resolveName(getName(), resourceName, NameScope.CHILD)));
398                             vfs.add(fo);
399                         }
400                     }
401                 }
402                 return vfs.toArray(EMPTY_ARRAY);
403             }
404             throw new FileNotFolderException(getName());
405         } catch (final FileNotFolderException fnfe) {
406             throw fnfe;
407         } catch (final DavException | IOException e) {
408             throw new FileSystemException(e.getMessage(), e);
409         } finally {
410             if (request != null) {
411                 request.releaseConnection();
412             }
413         }
414     }
415 
416     /**
417      * Rename the file.
418      */
419     @Override
420     protected void doRename(final FileObject newFile) throws Exception {
421         final String url = URIUtils.encodePath(toUrlString((GenericURLFileName) getName()));
422         final String dest = toUrlString((GenericURLFileName) newFile.getName(), false);
423         final HttpMove request = new HttpMove(url, dest, false);
424         setupRequest(request);
425         executeRequest(request);
426     }
427 
428     /**
429      * Sets an attribute of this file. Is only called if {@link #doGetType} does not return {@link FileType#IMAGINARY}.
430      */
431     @Override
432     protected void doSetAttribute(final String attrName, final Object value) throws Exception {
433         try {
434             final GenericURLFileName/../org/apache/commons/vfs2/provider/GenericURLFileName.html#GenericURLFileName">GenericURLFileName fileName = (GenericURLFileName) getName();
435             final String urlStr = toUrlString(fileName);
436             final DavPropertySet properties = new DavPropertySet();
437             final DavPropertyNameSet propertyNameSet = new DavPropertyNameSet();
438             final DavProperty<Object> property = new DefaultDavProperty<>(attrName, value, Namespace.EMPTY_NAMESPACE);
439             if (value != null) {
440                 properties.add(property);
441             } else {
442                 propertyNameSet.add(property.getName()); // remove property
443             }
444 
445             final HttpProppatch request = new HttpProppatch(urlStr, properties, propertyNameSet);
446             setupRequest(request);
447             final HttpResponse response = executeRequest(request);
448             if (!request.succeeded(response)) {
449                 throw new FileSystemException("Property '" + attrName + "' could not be set.");
450             }
451         } catch (final FileSystemException fse) {
452             throw fse;
453         } catch (final Exception e) {
454             throw new FileSystemException("vfs.provider.webdav/set-attributes", e, getName(), attrName);
455         }
456     }
457 
458     private HttpResponse executeRequest(final HttpUriRequest request) throws FileSystemException {
459         final HttpResponse response;
460 
461         try {
462             response = executeHttpUriRequest(request);
463             final int status = response.getStatusLine().getStatusCode();
464             if (status == HttpURLConnection.HTTP_NOT_FOUND || status == HttpURLConnection.HTTP_GONE) {
465                 throw new FileNotFoundException(request.getURI());
466             }
467 
468             if (request instanceof BaseDavRequest) {
469                 ((BaseDavRequest) request).checkSuccess(response);
470             }
471 
472             return response;
473         } catch (final FileSystemException fse) {
474             throw fse;
475         } catch (final IOException e) {
476             throw new FileSystemException(e);
477         } catch (final DavException e) {
478             throw ExceptionConverter.generate(e);
479         } finally {
480             if (request instanceof HttpRequestBase) {
481                 ((HttpRequestBase) request).releaseConnection();
482             }
483         }
484     }
485 
486     @Override
487     protected FileContentInfoFactory getFileContentInfoFactory() {
488         return new Webdav4FileContentInfoFactory();
489     }
490 
491     DavPropertySet getProperties(final GenericURLFileName name) throws FileSystemException {
492         return getProperties(name, DavConstants.PROPFIND_ALL_PROP, new DavPropertyNameSet(), false);
493     }
494 
495     DavPropertySet getProperties(final GenericURLFileName name, final DavPropertyNameSet nameSet, final boolean addEncoding)
496             throws FileSystemException {
497         return getProperties(name, DavConstants.PROPFIND_BY_PROPERTY, nameSet, addEncoding);
498     }
499 
500     DavPropertySet getProperties(final GenericURLFileName name, final int type, final DavPropertyNameSet nameSet,
501             final boolean addEncoding) throws FileSystemException {
502         try {
503             final String urlStr = toUrlString(name);
504             final HttpPropfind request = new HttpPropfind(urlStr, type, nameSet, DavConstants.DEPTH_0);
505             setupRequest(request);
506             final HttpResponse res = executeRequest(request);
507             if (request.succeeded(res)) {
508                 final MultiStatus multiStatus = request.getResponseBodyAsMultiStatus(res);
509                 final MultiStatusResponse response = multiStatus.getResponses()[0];
510                 final DavPropertySet props = response.getProperties(HttpStatus.SC_OK);
511                 if (addEncoding) {
512                     final ContentType resContentType = ContentType.getOrDefault(res.getEntity());
513                     final DavProperty<String> prop = new DefaultDavProperty<>(RESPONSE_CHARSET,
514                             resContentType.getCharset().name());
515                     props.add(prop);
516                 }
517                 return props;
518             }
519             return new DavPropertySet();
520         } catch (final FileSystemException fse) {
521             throw fse;
522         } catch (final Exception e) {
523             throw new FileSystemException("vfs.provider.webdav/get-property.error", e, getName(), name, type,
524                     nameSet.getContent(), addEncoding);
525         }
526     }
527 
528     DavProperty<?> getProperty(final GenericURLFileName fileName, final DavPropertyName name) throws FileSystemException {
529         final DavPropertyNameSet nameSet = new DavPropertyNameSet();
530         nameSet.add(name);
531         final DavPropertySet propertySet = getProperties(fileName, nameSet, false);
532         return propertySet.get(name);
533     }
534 
535     DavProperty<?> getProperty(final GenericURLFileName fileName, final String property) throws FileSystemException {
536         return getProperty(fileName, DavPropertyName.create(property));
537     }
538 
539     DavPropertySet getPropertyNames(final GenericURLFileName name) throws FileSystemException {
540         return getProperties(name, DavConstants.PROPFIND_PROPERTY_NAMES, new DavPropertyNameSet(), false);
541     }
542 
543     /**
544      * Convert the FileName to an encoded url String.
545      *
546      * @param name The FileName.
547      * @return The encoded URL String.
548      */
549     private String hrefString(final GenericURLFileName name) {
550         try {
551             final GenericURLFileNamenericURLFileName.html#GenericURLFileName">GenericURLFileName newFile = new GenericURLFileName(getInternalURI().getScheme(), name.getHostName(), name.getPort(), name.getDefaultPort(),
552                     null, null, name.getPath(), name.getType(), name.getQueryString());
553             return newFile.getURIEncoded(this.getUrlCharset());
554         } catch (final Exception e) {
555             return name.getURI();
556         }
557     }
558 
559     private boolean isCurrentFile(final String href, final GenericURLFileName fileName) {
560         String name = hrefString(fileName);
561         if (href.endsWith("/") && !name.endsWith("/")) {
562             name += "/";
563         }
564         return href.equals(name) || href.equals(fileName.getPath());
565     }
566 
567     private boolean isDirectory(final GenericURLFileName name) throws IOException {
568         try {
569             final DavProperty<?> property = getProperty(name, DavConstants.PROPERTY_RESOURCETYPE);
570             final Node node;
571             if (property != null && (node = (Node) property.getValue()) != null) {
572                 return node.getLocalName().equals(DavConstants.XML_COLLECTION);
573             }
574             return false;
575         } catch (final FileNotFoundException fse) {
576             throw new FileNotFolderException(name);
577         }
578     }
579 
580     /**
581      * Returns the resource name from the path.
582      *
583      * @param path the path to the file.
584      * @return The resource name
585      */
586     private String resourceName(String path) {
587         if (path.endsWith("/")) {
588             path = path.substring(0, path.length() - 1);
589         }
590         final int i = path.lastIndexOf("/");
591         return i >= 0 ? path.substring(i + 1) : path;
592     }
593 
594     private void setupRequest(final HttpUriRequest request) {
595         // NOTE: *FileSystemConfigBuilder takes care of redirect option and user agent.
596         request.addHeader("Cache-control", "no-cache");
597         request.addHeader("Cache-store", "no-store");
598         request.addHeader("Pragma", "no-cache");
599         request.addHeader("Expires", "0");
600     }
601 
602     /**
603      * Converts the given URLFileName to an encoded URL String to internally use in real DAV operations.
604      *
605      * @param name The FileName.
606      * @return The encoded URL String.
607      */
608     String toUrlString(final GenericURLFileName name) {
609         return toUrlString(name, true);
610     }
611 
612     /**
613      * Converts the given URLFileName to an encoded URL String to internally use in real DAV operations.
614      *
615      * @param name The FileName.
616      * @param includeUserInfo true if user information should be included.
617      * @return The encoded URL String.
618      */
619     private String toUrlString(final GenericURLFileName name, final boolean includeUserInfo) {
620         String user = null;
621         String password = null;
622         if (includeUserInfo) {
623             user = name.getUserName();
624             password = name.getPassword();
625         }
626         try {
627             final GenericURLFileNamenericURLFileName.html#GenericURLFileName">GenericURLFileName newFile = new GenericURLFileName(getInternalURI().getScheme(), name.getHostName(), name.getPort(), name.getDefaultPort(),
628                     user, password, name.getPath(), name.getType(), name.getQueryString());
629             return newFile.getURIEncoded(this.getUrlCharset());
630         } catch (final Exception e) {
631             return name.getURI();
632         }
633     }
634 }