You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2018/11/02 01:53:30 UTC

svn commit: r1845527 [2/2] - in /commons/proper/vfs/trunk: ./ commons-vfs2-examples/ commons-vfs2-examples/src/main/java/org/apache/commons/vfs2/example/ commons-vfs2-sandbox/ commons-vfs2/ commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ c...

Added: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileNameParser.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileNameParser.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileNameParser.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileNameParser.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4s;
+
+import org.apache.commons.vfs2.provider.FileNameParser;
+import org.apache.commons.vfs2.provider.GenericURLFileNameParser;
+
+/**
+ * <code>FileNameParser</code> implementation for http4s provider, setting default port to 443.
+ */
+public class Http4sFileNameParser extends GenericURLFileNameParser {
+
+    private static final int DEFAULT_PORT = 443;
+
+    private static final Http4sFileNameParser INSTANCE = new Http4sFileNameParser();
+
+    public Http4sFileNameParser() {
+        super(DEFAULT_PORT);
+    }
+
+    public static FileNameParser getInstance() {
+        return INSTANCE;
+    }
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileProvider.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileProvider.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileProvider.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/Http4sFileProvider.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4s;
+
+import org.apache.commons.vfs2.provider.http4.Http4FileProvider;
+
+/**
+ * http4s provider that uses HttpComponents HttpClient.
+ */
+public class Http4sFileProvider extends Http4FileProvider {
+
+    /**
+     * Construct a <code>Http4sFileProvider</code>.
+     */
+    public Http4sFileProvider() {
+        super();
+        setFileNameParser(Http4sFileNameParser.getInstance());
+    }
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/package.html
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/package.html?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/package.html (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/http4s/package.html Fri Nov  2 01:53:29 2018
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The HTTP4S File Provider</p>
+</body>

Modified: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/url/UrlFileProvider.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/url/UrlFileProvider.java?rev=1845527&r1=1845526&r2=1845527&view=diff
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/url/UrlFileProvider.java (original)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/url/UrlFileProvider.java Fri Nov  2 01:53:29 2018
@@ -16,8 +16,7 @@
  */
 package org.apache.commons.vfs2.provider.url;
 
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -48,31 +47,30 @@ public class UrlFileProvider extends Abs
      * Locates a file object, by absolute URI.
      *
      * @param baseFile The base FileObject.
-     * @param uri The uri of the file to locate.
+     * @param fileUri The uri of the file to locate.
      * @param fileSystemOptions The FileSystemOptions
      * @return The FileObject
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public synchronized FileObject findFile(final FileObject baseFile, final String uri,
+    public synchronized FileObject findFile(final FileObject baseFile, final String fileUri,
             final FileSystemOptions fileSystemOptions) throws FileSystemException {
         try {
-            final URL url = new URL(uri);
-
-            final URL rootUrl = new URL(url, "/");
-            final String key = this.getClass().getName() + rootUrl.toString();
+            final URI uri = URI.create(fileUri);
+            final URI rootUri = uri.resolve("/");
+            final String key = this.getClass().getName() + rootUri.toString();
             FileSystem fs = findFileSystem(key, fileSystemOptions);
             if (fs == null) {
-                final String extForm = rootUrl.toExternalForm();
+                final String extForm = rootUri.toString();
                 final FileName rootName = getContext().parseURI(extForm);
                 // final FileName rootName =
                 // new BasicFileName(rootUrl, FileName.ROOT_PATH);
                 fs = new UrlFileSystem(rootName, fileSystemOptions);
                 addFileSystem(key, fs);
             }
-            return fs.resolveFile(url.getPath());
-        } catch (final MalformedURLException e) {
-            throw new FileSystemException("vfs.provider.url/badly-formed-uri.error", uri, e);
+            return fs.resolveFile(uri.getPath());
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider.url/badly-formed-uri.error", fileUri, e);
         }
     }
 

Added: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIBitSets.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIBitSets.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIBitSets.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIBitSets.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,939 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.util;
+
+import java.util.BitSet;
+
+import org.apache.commons.vfs2.provider.GenericURLFileName;
+
+/**
+ * Internal URI encoding {@link BitSet} definitions.
+ * <P>
+ * This was forked from the {@link BitSet}s in <code>org.apache.commons.httpclient.URI</code>,
+ * in order to not be dependent on HttpClient v3 API, when generating and handling {@link GenericURLFileName}s, 
+ * but it should work with any different HTTP backend provider implementations.
+ */
+class URIBitSets {
+
+    // ---------------------- Generous characters for each component validation
+
+    /**
+     * The percent "%" character always has the reserved purpose of being the
+     * escape indicator, it must be escaped as "%25" in order to be used as
+     * data within a URI.
+     */
+    protected static final BitSet percent = new BitSet(256);
+    // Static initializer for percent
+    static {
+        percent.set('%');
+    }
+
+
+    /**
+     * BitSet for digit.
+     * <p><blockquote><pre>
+     * digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+     *            "8" | "9"
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet digit = new BitSet(256);
+    // Static initializer for digit
+    static {
+        for (int i = '0'; i <= '9'; i++) {
+            digit.set(i);
+        }
+    }
+
+
+    /**
+     * BitSet for alpha.
+     * <p><blockquote><pre>
+     * alpha         = lowalpha | upalpha
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet alpha = new BitSet(256);
+    // Static initializer for alpha
+    static {
+        for (int i = 'a'; i <= 'z'; i++) {
+            alpha.set(i);
+        }
+        for (int i = 'A'; i <= 'Z'; i++) {
+            alpha.set(i);
+        }
+    }
+
+
+    /**
+     * BitSet for alphanum (join of alpha &amp; digit).
+     * <p><blockquote><pre>
+     *  alphanum      = alpha | digit
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet alphanum = new BitSet(256);
+    // Static initializer for alphanum
+    static {
+        alphanum.or(alpha);
+        alphanum.or(digit);
+    }
+
+
+    /**
+     * BitSet for hex.
+     * <p><blockquote><pre>
+     * hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+     *                         "a" | "b" | "c" | "d" | "e" | "f"
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet hex = new BitSet(256);
+    // Static initializer for hex
+    static {
+        hex.or(digit);
+        for (int i = 'a'; i <= 'f'; i++) {
+            hex.set(i);
+        }
+        for (int i = 'A'; i <= 'F'; i++) {
+            hex.set(i);
+        }
+    }
+
+
+    /**
+     * BitSet for escaped.
+     * <p><blockquote><pre>
+     * escaped       = "%" hex hex
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet escaped = new BitSet(256);
+    // Static initializer for escaped
+    static {
+        escaped.or(percent);
+        escaped.or(hex);
+    }
+
+
+    /**
+     * BitSet for mark.
+     * <p><blockquote><pre>
+     * mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+     *                 "(" | ")"
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet mark = new BitSet(256);
+    // Static initializer for mark
+    static {
+        mark.set('-');
+        mark.set('_');
+        mark.set('.');
+        mark.set('!');
+        mark.set('~');
+        mark.set('*');
+        mark.set('\'');
+        mark.set('(');
+        mark.set(')');
+    }
+
+
+    /**
+     * Data characters that are allowed in a URI but do not have a reserved
+     * purpose are called unreserved.
+     * <p><blockquote><pre>
+     * unreserved    = alphanum | mark
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet unreserved = new BitSet(256);
+    // Static initializer for unreserved
+    static {
+        unreserved.or(alphanum);
+        unreserved.or(mark);
+    }
+
+
+    /**
+     * BitSet for reserved.
+     * <p><blockquote><pre>
+     * reserved      = ";" | "/" | "?" | ":" | "@" | "&amp;" | "=" | "+" |
+     *                 "$" | ","
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet reserved = new BitSet(256);
+    // Static initializer for reserved
+    static {
+        reserved.set(';');
+        reserved.set('/');
+        reserved.set('?');
+        reserved.set(':');
+        reserved.set('@');
+        reserved.set('&');
+        reserved.set('=');
+        reserved.set('+');
+        reserved.set('$');
+        reserved.set(',');
+    }
+
+
+    /**
+     * BitSet for uric.
+     * <p><blockquote><pre>
+     * uric          = reserved | unreserved | escaped
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet uric = new BitSet(256);
+    // Static initializer for uric
+    static {
+        uric.or(reserved);
+        uric.or(unreserved);
+        uric.or(escaped);
+    }
+
+
+    /**
+     * BitSet for fragment (alias for uric).
+     * <p><blockquote><pre>
+     * fragment      = *uric
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet fragment = uric;
+
+
+    /**
+     * BitSet for query (alias for uric).
+     * <p><blockquote><pre>
+     * query         = *uric
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet query = uric;
+
+
+    /**
+     * BitSet for pchar.
+     * <p><blockquote><pre>
+     * pchar         = unreserved | escaped |
+     *                 ":" | "@" | "&amp;" | "=" | "+" | "$" | ","
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet pchar = new BitSet(256);
+    // Static initializer for pchar
+    static {
+        pchar.or(unreserved);
+        pchar.or(escaped);
+        pchar.set(':');
+        pchar.set('@');
+        pchar.set('&');
+        pchar.set('=');
+        pchar.set('+');
+        pchar.set('$');
+        pchar.set(',');
+    }
+
+
+    /**
+     * BitSet for param (alias for pchar).
+     * <p><blockquote><pre>
+     * param         = *pchar
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet param = pchar;
+
+
+    /**
+     * BitSet for segment.
+     * <p><blockquote><pre>
+     * segment       = *pchar *( ";" param )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet segment = new BitSet(256);
+    // Static initializer for segment
+    static {
+        segment.or(pchar);
+        segment.set(';');
+        segment.or(param);
+    }
+
+
+    /**
+     * BitSet for path segments.
+     * <p><blockquote><pre>
+     * path_segments = segment *( "/" segment )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet path_segments = new BitSet(256);
+    // Static initializer for path_segments
+    static {
+        path_segments.set('/');
+        path_segments.or(segment);
+    }
+
+
+    /**
+     * URI absolute path.
+     * <p><blockquote><pre>
+     * abs_path      = "/"  path_segments
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet abs_path = new BitSet(256);
+    // Static initializer for abs_path
+    static {
+        abs_path.set('/');
+        abs_path.or(path_segments);
+    }
+
+
+    /**
+     * URI bitset for encoding typical non-slash characters.
+     * <p><blockquote><pre>
+     * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+     *                 "&amp;" | "=" | "+" | "$" | ","
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet uric_no_slash = new BitSet(256);
+    // Static initializer for uric_no_slash
+    static {
+        uric_no_slash.or(unreserved);
+        uric_no_slash.or(escaped);
+        uric_no_slash.set(';');
+        uric_no_slash.set('?');
+        uric_no_slash.set(';');
+        uric_no_slash.set('@');
+        uric_no_slash.set('&');
+        uric_no_slash.set('=');
+        uric_no_slash.set('+');
+        uric_no_slash.set('$');
+        uric_no_slash.set(',');
+    }
+    
+
+    /**
+     * URI bitset that combines uric_no_slash and uric.
+     * <p><blockquote><pre>
+     * opaque_part   = uric_no_slash *uric
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet opaque_part = new BitSet(256);
+    // Static initializer for opaque_part
+    static {
+        // it's generous. because first character must not include a slash
+        opaque_part.or(uric_no_slash);
+        opaque_part.or(uric);
+    }
+    
+
+    /**
+     * URI bitset that combines absolute path and opaque part.
+     * <p><blockquote><pre>
+     * path          = [ abs_path | opaque_part ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet path = new BitSet(256);
+    // Static initializer for path
+    static {
+        path.or(abs_path);
+        path.or(opaque_part);
+    }
+
+
+    /**
+     * Port, a logical alias for digit.
+     */
+    protected static final BitSet port = digit;
+
+
+    /**
+     * Bitset that combines digit and dot fo IPv$address.
+     * <p><blockquote><pre>
+     * IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet IPv4address = new BitSet(256);
+    // Static initializer for IPv4address
+    static {
+        IPv4address.or(digit);
+        IPv4address.set('.');
+    }
+
+
+    /**
+     * RFC 2373.
+     * <p><blockquote><pre>
+     * IPv6address = hexpart [ ":" IPv4address ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet IPv6address = new BitSet(256);
+    // Static initializer for IPv6address reference
+    static {
+        IPv6address.or(hex); // hexpart
+        IPv6address.set(':');
+        IPv6address.or(IPv4address);
+    }
+
+
+    /**
+     * RFC 2732, 2373.
+     * <p><blockquote><pre>
+     * IPv6reference   = "[" IPv6address "]"
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet IPv6reference = new BitSet(256);
+    // Static initializer for IPv6reference
+    static {
+        IPv6reference.set('[');
+        IPv6reference.or(IPv6address);
+        IPv6reference.set(']');
+    }
+
+
+    /**
+     * BitSet for toplabel.
+     * <p><blockquote><pre>
+     * toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet toplabel = new BitSet(256);
+    // Static initializer for toplabel
+    static {
+        toplabel.or(alphanum);
+        toplabel.set('-');
+    }
+
+
+    /**
+     * BitSet for domainlabel.
+     * <p><blockquote><pre>
+     * domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet domainlabel = toplabel;
+
+
+    /**
+     * BitSet for hostname.
+     * <p><blockquote><pre>
+     * hostname      = *( domainlabel "." ) toplabel [ "." ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet hostname = new BitSet(256);
+    // Static initializer for hostname
+    static {
+        hostname.or(toplabel);
+        // hostname.or(domainlabel);
+        hostname.set('.');
+    }
+
+
+    /**
+     * BitSet for host.
+     * <p><blockquote><pre>
+     * host          = hostname | IPv4address | IPv6reference
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet host = new BitSet(256);
+    // Static initializer for host
+    static {
+        host.or(hostname);
+        // host.or(IPv4address);
+        host.or(IPv6reference); // IPv4address
+    }
+
+
+    /**
+     * BitSet for hostport.
+     * <p><blockquote><pre>
+     * hostport      = host [ ":" port ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet hostport = new BitSet(256);
+    // Static initializer for hostport
+    static {
+        hostport.or(host);
+        hostport.set(':');
+        hostport.or(port);
+    }
+
+
+    /**
+     * Bitset for userinfo.
+     * <p><blockquote><pre>
+     * userinfo      = *( unreserved | escaped |
+     *                    ";" | ":" | "&amp;" | "=" | "+" | "$" | "," )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet userinfo = new BitSet(256);
+    // Static initializer for userinfo
+    static {
+        userinfo.or(unreserved);
+        userinfo.or(escaped);
+        userinfo.set(';');
+        userinfo.set(':');
+        userinfo.set('&');
+        userinfo.set('=');
+        userinfo.set('+');
+        userinfo.set('$');
+        userinfo.set(',');
+    }
+
+
+    /**
+     * BitSet for within the userinfo component like user and password.
+     */
+    public static final BitSet within_userinfo = new BitSet(256);
+    // Static initializer for within_userinfo
+    static {
+        within_userinfo.or(userinfo);
+        within_userinfo.clear(';'); // reserved within authority
+        within_userinfo.clear(':');
+        within_userinfo.clear('@');
+        within_userinfo.clear('?');
+        within_userinfo.clear('/');
+    }
+
+
+    /**
+     * Bitset for server.
+     * <p><blockquote><pre>
+     * server        = [ [ userinfo "@" ] hostport ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet server = new BitSet(256);
+    // Static initializer for server
+    static {
+        server.or(userinfo);
+        server.set('@');
+        server.or(hostport);
+    }
+
+
+    /**
+     * BitSet for reg_name.
+     * <p><blockquote><pre>
+     * reg_name      = 1*( unreserved | escaped | "$" | "," |
+     *                     ";" | ":" | "@" | "&amp;" | "=" | "+" )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet reg_name = new BitSet(256);
+    // Static initializer for reg_name
+    static {
+        reg_name.or(unreserved);
+        reg_name.or(escaped);
+        reg_name.set('$');
+        reg_name.set(',');
+        reg_name.set(';');
+        reg_name.set(':');
+        reg_name.set('@');
+        reg_name.set('&');
+        reg_name.set('=');
+        reg_name.set('+');
+    }
+
+
+    /**
+     * BitSet for authority.
+     * <p><blockquote><pre>
+     * authority     = server | reg_name
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet authority = new BitSet(256);
+    // Static initializer for authority
+    static {
+        authority.or(server);
+        authority.or(reg_name);
+    }
+
+
+    /**
+     * BitSet for scheme.
+     * <p><blockquote><pre>
+     * scheme        = alpha *( alpha | digit | "+" | "-" | "." )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet scheme = new BitSet(256);
+    // Static initializer for scheme
+    static {
+        scheme.or(alpha);
+        scheme.or(digit);
+        scheme.set('+');
+        scheme.set('-');
+        scheme.set('.');
+    }
+
+
+    /**
+     * BitSet for rel_segment.
+     * <p><blockquote><pre>
+     * rel_segment   = 1*( unreserved | escaped |
+     *                     ";" | "@" | "&amp;" | "=" | "+" | "$" | "," )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet rel_segment = new BitSet(256);
+    // Static initializer for rel_segment
+    static {
+        rel_segment.or(unreserved);
+        rel_segment.or(escaped);
+        rel_segment.set(';');
+        rel_segment.set('@');
+        rel_segment.set('&');
+        rel_segment.set('=');
+        rel_segment.set('+');
+        rel_segment.set('$');
+        rel_segment.set(',');
+    }
+
+
+    /**
+     * BitSet for rel_path.
+     * <p><blockquote><pre>
+     * rel_path      = rel_segment [ abs_path ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet rel_path = new BitSet(256);
+    // Static initializer for rel_path
+    static {
+        rel_path.or(rel_segment);
+        rel_path.or(abs_path);
+    }
+
+
+    /**
+     * BitSet for net_path.
+     * <p><blockquote><pre>
+     * net_path      = "//" authority [ abs_path ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet net_path = new BitSet(256);
+    // Static initializer for net_path
+    static {
+        net_path.set('/');
+        net_path.or(authority);
+        net_path.or(abs_path);
+    }
+    
+
+    /**
+     * BitSet for hier_part.
+     * <p><blockquote><pre>
+     * hier_part     = ( net_path | abs_path ) [ "?" query ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet hier_part = new BitSet(256);
+    // Static initializer for hier_part
+    static {
+        hier_part.or(net_path);
+        hier_part.or(abs_path);
+        // hier_part.set('?'); aleady included
+        hier_part.or(query);
+    }
+
+
+    /**
+     * BitSet for relativeURI.
+     * <p><blockquote><pre>
+     * relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet relativeURI = new BitSet(256);
+    // Static initializer for relativeURI
+    static {
+        relativeURI.or(net_path);
+        relativeURI.or(abs_path);
+        relativeURI.or(rel_path);
+        // relativeURI.set('?'); aleady included
+        relativeURI.or(query);
+    }
+
+
+    /**
+     * BitSet for absoluteURI.
+     * <p><blockquote><pre>
+     * absoluteURI   = scheme ":" ( hier_part | opaque_part )
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet absoluteURI = new BitSet(256);
+    // Static initializer for absoluteURI
+    static {
+        absoluteURI.or(scheme);
+        absoluteURI.set(':');
+        absoluteURI.or(hier_part);
+        absoluteURI.or(opaque_part);
+    }
+
+
+    /**
+     * BitSet for URI-reference.
+     * <p><blockquote><pre>
+     * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+     * </pre></blockquote><p>
+     */
+    protected static final BitSet URI_reference = new BitSet(256);
+    // Static initializer for URI_reference
+    static {
+        URI_reference.or(absoluteURI);
+        URI_reference.or(relativeURI);
+        URI_reference.set('#');
+        URI_reference.or(fragment);
+    }
+
+    // ---------------------------- Characters disallowed within the URI syntax
+    // Excluded US-ASCII Characters are like control, space, delims and unwise
+
+    /**
+     * BitSet for control.
+     */
+    public static final BitSet control = new BitSet(256);
+    // Static initializer for control
+    static {
+        for (int i = 0; i <= 0x1F; i++) {
+            control.set(i);
+        }
+        control.set(0x7F);
+    }
+
+    /**
+     * BitSet for space.
+     */
+    public static final BitSet space = new BitSet(256);
+    // Static initializer for space
+    static {
+        space.set(0x20);
+    }
+
+
+    /**
+     * BitSet for delims.
+     */
+    public static final BitSet delims = new BitSet(256);
+    // Static initializer for delims
+    static {
+        delims.set('<');
+        delims.set('>');
+        delims.set('#');
+        delims.set('%');
+        delims.set('"');
+    }
+
+
+    /**
+     * BitSet for unwise.
+     */
+    public static final BitSet unwise = new BitSet(256);
+    // Static initializer for unwise
+    static {
+        unwise.set('{');
+        unwise.set('}');
+        unwise.set('|');
+        unwise.set('\\');
+        unwise.set('^');
+        unwise.set('[');
+        unwise.set(']');
+        unwise.set('`');
+    }
+
+
+    /**
+     * Disallowed rel_path before escaping.
+     */
+    public static final BitSet disallowed_rel_path = new BitSet(256);
+    // Static initializer for disallowed_rel_path
+    static {
+        disallowed_rel_path.or(uric);
+        disallowed_rel_path.andNot(rel_path);
+    }
+
+
+    /**
+     * Disallowed opaque_part before escaping.
+     */
+    public static final BitSet disallowed_opaque_part = new BitSet(256);
+    // Static initializer for disallowed_opaque_part
+    static {
+        disallowed_opaque_part.or(uric);
+        disallowed_opaque_part.andNot(opaque_part);
+    }
+
+    // ----------------------- Characters allowed within and for each component
+
+    /**
+     * Those characters that are allowed for the authority component.
+     */
+    public static final BitSet allowed_authority = new BitSet(256);
+    // Static initializer for allowed_authority
+    static {
+        allowed_authority.or(authority);
+        allowed_authority.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed for the opaque_part.
+     */
+    public static final BitSet allowed_opaque_part = new BitSet(256);
+    // Static initializer for allowed_opaque_part 
+    static {
+        allowed_opaque_part.or(opaque_part);
+        allowed_opaque_part.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed for the reg_name.
+     */
+    public static final BitSet allowed_reg_name = new BitSet(256);
+    // Static initializer for allowed_reg_name 
+    static {
+        allowed_reg_name.or(reg_name);
+        // allowed_reg_name.andNot(percent);
+        allowed_reg_name.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed for the userinfo component.
+     */
+    public static final BitSet allowed_userinfo = new BitSet(256);
+    // Static initializer for allowed_userinfo
+    static {
+        allowed_userinfo.or(userinfo);
+        // allowed_userinfo.andNot(percent);
+        allowed_userinfo.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed for within the userinfo component.
+     */
+    public static final BitSet allowed_within_userinfo = new BitSet(256);
+    // Static initializer for allowed_within_userinfo
+    static {
+        allowed_within_userinfo.or(within_userinfo);
+        allowed_within_userinfo.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed for the IPv6reference component.
+     * The characters '[', ']' in IPv6reference should be excluded.
+     */
+    public static final BitSet allowed_IPv6reference = new BitSet(256);
+    // Static initializer for allowed_IPv6reference
+    static {
+        allowed_IPv6reference.or(IPv6reference);
+        // allowed_IPv6reference.andNot(unwise);
+        allowed_IPv6reference.clear('[');
+        allowed_IPv6reference.clear(']');
+    }
+
+
+    /**
+     * Those characters that are allowed for the host component.
+     * The characters '[', ']' in IPv6reference should be excluded.
+     */
+    public static final BitSet allowed_host = new BitSet(256);
+    // Static initializer for allowed_host
+    static {
+        allowed_host.or(hostname);
+        allowed_host.or(allowed_IPv6reference);
+    }
+
+
+    /**
+     * Those characters that are allowed for the authority component.
+     */
+    public static final BitSet allowed_within_authority = new BitSet(256);
+    // Static initializer for allowed_within_authority
+    static {
+        allowed_within_authority.or(server);
+        allowed_within_authority.or(reg_name);
+        allowed_within_authority.clear(';');
+        allowed_within_authority.clear(':');
+        allowed_within_authority.clear('@');
+        allowed_within_authority.clear('?');
+        allowed_within_authority.clear('/');
+    }
+
+
+    /**
+     * Those characters that are allowed for the abs_path.
+     */
+    public static final BitSet allowed_abs_path = new BitSet(256);
+    // Static initializer for allowed_abs_path
+    static {
+        allowed_abs_path.or(abs_path);
+        // allowed_abs_path.set('/');  // aleady included
+        allowed_abs_path.andNot(percent);
+        allowed_abs_path.clear('+');
+    }
+
+
+    /**
+     * Those characters that are allowed for the rel_path.
+     */
+    public static final BitSet allowed_rel_path = new BitSet(256);
+    // Static initializer for allowed_rel_path
+    static {
+        allowed_rel_path.or(rel_path);
+        allowed_rel_path.clear('%');
+        allowed_rel_path.clear('+');
+    }
+
+
+    /**
+     * Those characters that are allowed within the path.
+     */
+    public static final BitSet allowed_within_path = new BitSet(256);
+    // Static initializer for allowed_within_path
+    static {
+        allowed_within_path.or(abs_path);
+        allowed_within_path.clear('/');
+        allowed_within_path.clear(';');
+        allowed_within_path.clear('=');
+        allowed_within_path.clear('?');
+    }
+
+
+    /**
+     * Those characters that are allowed for the query component.
+     */
+    public static final BitSet allowed_query = new BitSet(256);
+    // Static initializer for allowed_query
+    static {
+        allowed_query.or(uric);
+        allowed_query.clear('%');
+    }
+
+
+    /**
+     * Those characters that are allowed within the query component.
+     */
+    public static final BitSet allowed_within_query = new BitSet(256);
+    // Static initializer for allowed_within_query
+    static {
+        allowed_within_query.or(allowed_query);
+        allowed_within_query.andNot(reserved); // excluded 'reserved'
+    }
+
+
+    /**
+     * Those characters that are allowed for the fragment component.
+     */
+    public static final BitSet allowed_fragment = new BitSet(256);
+    // Static initializer for allowed_fragment
+    static {
+        allowed_fragment.or(uric);
+        allowed_fragment.clear('%');
+    }
+
+    private URIBitSets() {
+    }
+
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIUtils.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIUtils.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/main/java/org/apache/commons/vfs2/util/URIUtils.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.util.BitSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs2.provider.GenericURLFileName;
+
+/**
+ * The URI escape and character encoding and decoding utility.
+ * <P>
+ * This was forked from some needed methods such as <code>#encodePath(...)</code> in <code>org.apache.commons.httpclient.util.URIUtil</code>,
+ * in order to not be dependent on HttpClient v3 API, when generating and handling {@link GenericURLFileName}s, 
+ * but it should work with any different HTTP backend provider implementations.
+ */
+public class URIUtils {
+
+    private static final Log LOG = LogFactory.getLog(URIUtils.class);
+
+    /**
+     * The default charset of the protocol.  RFC 2277, 2396
+     */
+    private static final String DEFAULT_PROTOCOL_CHARSET = "UTF-8";
+
+    private URIUtils() {
+    }
+
+    /**
+     * Escape and encode a string regarded as the path component of an URI with
+     * the default protocol charset.
+     *
+     * @param unescaped an unescaped string
+     * @return the escaped string
+     * 
+     * @throws URISyntaxException if the default protocol charset is not supported
+     */
+    public static String encodePath(String unescaped) throws URISyntaxException {
+        return encodePath(unescaped, DEFAULT_PROTOCOL_CHARSET);
+    }
+
+    /**
+     * Escape and encode a string regarded as the path component of an URI with
+     * a given charset.
+     *
+     * @param unescaped an unescaped string
+     * @param charset the charset
+     * @return the escaped string
+     * 
+     * @throws URISyntaxException if the charset is not supported
+     */
+    public static String encodePath(String unescaped, String charset) throws URISyntaxException {
+        if (unescaped == null) {
+            throw new IllegalArgumentException("The string to encode may not be null.");
+        }
+
+        return encode(unescaped, URIBitSets.allowed_abs_path, charset);
+    }
+
+    private static String encode(String unescaped, BitSet allowed, String charset) throws URISyntaxException {
+        byte[] rawdata = URLCodecUtils.encodeUrl(allowed, EncodingUtils.getBytes(unescaped, charset));
+        return EncodingUtils.getAsciiString(rawdata, 0, rawdata.length);
+    }
+
+    /**
+     * Internal URL codec utilities.
+     * <P>
+     * This was forked from some needed methods such as <code>#encodeUrl(...)</code> and <code>#hexDigit(int)</code>
+     * in <code>org.apache.commons.codec.net.URLCodec</code>, as commons-codec library cannot be pulled in transitively
+     * via Http Client v3 library any more.
+     */
+    private static class URLCodecUtils {
+
+        private static final byte ESCAPE_CHAR = '%';
+
+        private static final BitSet WWW_FORM_URL_SAFE = new BitSet(256);
+
+        // Static initializer for www_form_url
+        static {
+            // alpha characters
+            for (int i = 'a'; i <= 'z'; i++) {
+                WWW_FORM_URL_SAFE.set(i);
+            }
+            for (int i = 'A'; i <= 'Z'; i++) {
+                WWW_FORM_URL_SAFE.set(i);
+            }
+            // numeric characters
+            for (int i = '0'; i <= '9'; i++) {
+                WWW_FORM_URL_SAFE.set(i);
+            }
+            // special chars
+            WWW_FORM_URL_SAFE.set('-');
+            WWW_FORM_URL_SAFE.set('_');
+            WWW_FORM_URL_SAFE.set('.');
+            WWW_FORM_URL_SAFE.set('*');
+            // blank to be replaced with +
+            WWW_FORM_URL_SAFE.set(' ');
+        }
+
+        /**
+         * Radix used in encoding and decoding.
+         */
+        private static final int RADIX = 16;
+
+        private URLCodecUtils() {
+        }
+
+        static final byte[] encodeUrl(BitSet urlsafe, final byte[] bytes) {
+            if (bytes == null) {
+                return null;
+            }
+            if (urlsafe == null) {
+                urlsafe = WWW_FORM_URL_SAFE;
+            }
+
+            final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+            for (final byte c : bytes) {
+                int b = c;
+                if (b < 0) {
+                    b = 256 + b;
+                }
+                if (urlsafe.get(b)) {
+                    if (b == ' ') {
+                        b = '+';
+                    }
+                    buffer.write(b);
+                } else {
+                    buffer.write(ESCAPE_CHAR);
+                    final char hex1 = hexDigit(b >> 4);
+                    final char hex2 = hexDigit(b);
+                    buffer.write(hex1);
+                    buffer.write(hex2);
+                }
+            }
+            return buffer.toByteArray();
+        }
+
+        private static char hexDigit(final int b) {
+            return Character.toUpperCase(Character.forDigit(b & 0xF, RADIX));
+        }
+    }
+
+    /**
+     * Internal character encoding utilities.
+     * <P>
+     * This was forked from some needed methods such as <code>#getBytes(...)</code> and <code>#getAsciiString(...)</code>
+     * in <code>org.apache.commons.httpclient.util.EncodingUtil</code>,
+     * in order to not be dependent on HttpClient v3 API, when generating and handling {@link GenericURLFileName}s, 
+     * but it should work with any different HTTP backend provider implementations.
+     */
+    private static class EncodingUtils {
+
+        private EncodingUtils() {
+        }
+
+        /**
+         * Converts the specified string to a byte array.  If the charset is not supported the
+         * default system charset is used.
+         *
+         * @param data the string to be encoded
+         * @param charset the desired character encoding
+         * @return The resulting byte array.
+         */
+        static byte[] getBytes(final String data, String charset) {
+            if (data == null) {
+                throw new IllegalArgumentException("data may not be null");
+            }
+
+            if (charset == null || charset.length() == 0) {
+                throw new IllegalArgumentException("charset may not be null or empty");
+            }
+
+            try {
+                return data.getBytes(charset);
+            } catch (UnsupportedEncodingException e) {
+
+                if (LOG.isWarnEnabled()) {
+                    LOG.warn("Unsupported encoding: " + charset + ". System encoding used.");
+                }
+
+                return data.getBytes();
+            }
+        }
+
+        /**
+         * Converts the byte array of ASCII characters to a string. This method is
+         * to be used when decoding content of HTTP elements (such as response
+         * headers)
+         *
+         * @param data the byte array to be encoded
+         * @param offset the index of the first byte to encode
+         * @param length the number of bytes to encode 
+         * @return The string representation of the byte array
+         */
+        static String getAsciiString(final byte[] data, int offset, int length) {
+            try {
+                return new String(data, offset, length, "US-ASCII");
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException("US-ASCII charset is not supported.");
+            }
+        }
+    }
+
+}

Modified: commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/DefaultFileContentTest.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/DefaultFileContentTest.java?rev=1845527&r1=1845526&r2=1845527&view=diff
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/DefaultFileContentTest.java (original)
+++ commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/DefaultFileContentTest.java Fri Nov  2 01:53:29 2018
@@ -1,3 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package org.apache.commons.vfs2.provider;
 
 import org.apache.commons.vfs2.FileObject;

Added: commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4FilesCacheTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4FilesCacheTestCase.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4FilesCacheTestCase.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4FilesCacheTestCase.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4.test;
+
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.VFS;
+import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs2.provider.http4.Http4FileProvider;
+import org.junit.Assert;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests https://issues.apache.org/jira/browse/VFS-426.
+ */
+public class Http4FilesCacheTestCase extends TestCase {
+
+    // TODO: VFS-360 - Remove this manual registration of http4 once http4 becomes part of standard providers.
+    @Override
+    protected void setUp() throws Exception {
+        final DefaultFileSystemManager manager = (DefaultFileSystemManager) VFS.getManager();
+        if (!manager.hasProvider("http4")) {
+            manager.addProvider("http4", new Http4FileProvider());
+        }
+    }
+
+    /**
+     * Tests https://issues.apache.org/jira/browse/VFS-426
+     */
+    @Test
+    public void testQueryStringUrls() throws FileSystemException {
+        final String noQueryStringUrl = "http4://commons.apache.org/vfs";
+        final String queryStringUrl = "http4://commons.apache.org/vfs?query=string";
+        final String queryStringUrl2 = "http4://commons.apache.org/vfs?query=string&more=stuff";
+
+        final FileSystemManager fileSystemManager = VFS.getManager();
+
+        final FileObject noQueryFile = fileSystemManager.resolveFile(noQueryStringUrl);
+        Assert.assertEquals(noQueryStringUrl, noQueryFile.getURL().toExternalForm());
+
+        final FileObject queryFile = fileSystemManager.resolveFile(queryStringUrl);
+        Assert.assertEquals(queryStringUrl, queryFile.getURL().toExternalForm()); // failed for VFS-426
+
+        final FileObject queryFile2 = fileSystemManager.resolveFile(queryStringUrl2);
+        Assert.assertEquals(queryStringUrl2, queryFile2.getURL().toExternalForm()); // failed for VFS-426
+    }
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4GetContentInfoTest.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4GetContentInfoTest.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4GetContentInfoTest.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4GetContentInfoTest.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4.test;
+
+import org.apache.commons.vfs2.FileContent;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.VFS;
+import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs2.provider.http4.Http4FileProvider;
+import org.junit.Assert;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests VFS-427 NPE on Http4FileObject.getContent().getContentInfo().
+ */
+public class Http4GetContentInfoTest extends TestCase {
+
+    // TODO: VFS-360 - Remove this manual registration of http4 once http4 becomes part of standard providers.
+    @Override
+    protected void setUp() throws Exception {
+        final DefaultFileSystemManager manager = (DefaultFileSystemManager) VFS.getManager();
+        if (!manager.hasProvider("http4")) {
+            manager.addProvider("http4", new Http4FileProvider());
+        }
+    }
+
+    /**
+     * Tests VFS-427 NPE on Http4FileObject.getContent().getContentInfo().
+     *
+     * @throws FileSystemException thrown when the getContentInfo API fails.
+     */
+    @Test
+    public void testGetContentInfo() throws FileSystemException {
+        final FileSystemManager fsManager = VFS.getManager();
+        final FileObject fo = fsManager.resolveFile("http4://www.apache.org/licenses/LICENSE-2.0.txt");
+        final FileContent content = fo.getContent();
+        Assert.assertNotNull(content);
+        // Used to NPE before fix:
+        content.getContentInfo();
+    }
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4ProviderTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4ProviderTestCase.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4ProviderTestCase.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4/test/Http4ProviderTestCase.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.vfs2.FileNotFolderException;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.FileSystemOptions;
+import org.apache.commons.vfs2.VFS;
+import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs2.provider.http4.Http4FileProvider;
+import org.apache.commons.vfs2.provider.http4.Http4FileSystemConfigBuilder;
+import org.apache.commons.vfs2.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs2.test.ProviderTestSuite;
+import org.apache.commons.vfs2.util.FreeSocketPortUtil;
+import org.apache.commons.vfs2.util.NHttpFileServer;
+import org.junit.Assert;
+
+import junit.framework.Test;
+
+/**
+ * Test cases for the HTTP4 provider.
+ *
+ */
+public class Http4ProviderTestCase extends AbstractProviderTestConfig {
+
+    private static NHttpFileServer Server;
+
+    private static int SocketPort;
+
+    private static final String TEST_URI = "test.http.uri";
+
+    /**
+     * Use %40 for @ in URLs
+     */
+    private static String ConnectionUri;
+
+    private static String getSystemTestUriOverride() {
+        return System.getProperty(TEST_URI);
+    }
+
+    /**
+     * Creates and starts an embedded Apache HTTP Server (HttpComponents).
+     *
+     * @throws Exception
+     */
+    private static void setUpClass() throws Exception {
+        Server = NHttpFileServer.start(SocketPort, new File(getTestDirectory()), 5000);
+    }
+
+    /**
+     * Creates a new test suite.
+     *
+     * @return a new test suite.
+     * @throws Exception Thrown when the suite cannot be constructed.
+     */
+    public static Test suite() throws Exception {
+        return new ProviderTestSuite(new Http4ProviderTestCase()) {
+            /**
+             * Adds base tests - excludes the nested test cases.
+             */
+            @Override
+            protected void addBaseTests() throws Exception {
+                super.addBaseTests();
+                addTests(Http4ProviderTestCase.class);
+            }
+
+            @Override
+            protected void setUp() throws Exception {
+                if (getSystemTestUriOverride() == null) {
+                    setUpClass();
+                }
+                super.setUp();
+            }
+
+            @Override
+            protected void tearDown() throws Exception {
+                tearDownClass();
+                super.tearDown();
+            }
+        };
+    }
+
+    /**
+     * Stops the embedded Apache HTTP Server.
+     *
+     * @throws IOException
+     */
+    private static void tearDownClass() throws IOException {
+        if (Server != null) {
+            Server.shutdown(5000, TimeUnit.SECONDS);
+        }
+    }
+
+    /**
+     * Builds a new test case.
+     *
+     * @throws IOException Thrown if a free local socket port cannot be found.
+     */
+    public Http4ProviderTestCase() throws IOException {
+        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
+        // Use %40 for @ in a URL
+        ConnectionUri = "http4://localhost:" + SocketPort;
+    }
+
+    private void checkReadTestsFolder(final FileObject file) throws FileSystemException {
+        Assert.assertNotNull(file.getChildren());
+        Assert.assertTrue(file.getChildren().length > 0);
+    }
+
+    // TODO: VFS-360 - Remove this manual registration of http4 once http4 becomes part of standard providers.
+    @Override
+    protected void setUp() throws Exception {
+        final DefaultFileSystemManager manager = (DefaultFileSystemManager) VFS.getManager();
+        if (!manager.hasProvider("http4")) {
+            manager.addProvider("http4", new Http4FileProvider());
+        }
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    @Override
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception {
+        String uri = getSystemTestUriOverride();
+        if (uri == null) {
+            uri = ConnectionUri;
+        }
+        return manager.resolveFile(uri);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    @Override
+    public void prepare(final DefaultFileSystemManager manager) throws Exception {
+        if (!manager.hasProvider("http4")) {
+            manager.addProvider("http4", new Http4FileProvider());
+        }
+    }
+
+    private void testResloveFolderSlash(final String uri, final boolean followRedirect) throws FileSystemException {
+        VFS.getManager().getFilesCache().close();
+        final FileSystemOptions opts = new FileSystemOptions();
+        Http4FileSystemConfigBuilder.getInstance().setFollowRedirect(opts, followRedirect);
+        final FileObject file = VFS.getManager().resolveFile(uri, opts);
+        try {
+            checkReadTestsFolder(file);
+        } catch (final FileNotFolderException e) {
+            // Expected: VFS HTTP does not support listing children yet.
+        }
+    }
+
+    public void testResloveFolderSlashNoRedirectOff() throws FileSystemException {
+        testResloveFolderSlash(ConnectionUri + "/read-tests", false);
+    }
+
+    public void testResloveFolderSlashNoRedirectOn() throws FileSystemException {
+        testResloveFolderSlash(ConnectionUri + "/read-tests", true);
+    }
+
+    public void testResloveFolderSlashYesRedirectOff() throws FileSystemException {
+        testResloveFolderSlash(ConnectionUri + "/read-tests/", false);
+    }
+
+    public void testResloveFolderSlashYesRedirectOn() throws FileSystemException {
+        testResloveFolderSlash(ConnectionUri + "/read-tests/", true);
+    }
+
+    // Test no longer passing 2016/04/28
+    public void ignoreTestHttp405() throws FileSystemException {
+        final FileObject f = VFS.getManager()
+                .resolveFile("http4://www.w3schools.com/webservices/tempconvert.asmx?action=WSDL");
+        assert f.getContent().getSize() > 0;
+    }
+
+    /** Ensure VFS-453 options are present. */
+    public void testHttpTimeoutConfig() throws FileSystemException {
+        final FileSystemOptions opts = new FileSystemOptions();
+        final Http4FileSystemConfigBuilder builder = Http4FileSystemConfigBuilder.getInstance();
+
+        // ensure defaults are 0
+        assertEquals(0, builder.getConnectionTimeout(opts));
+        assertEquals(0, builder.getSoTimeout(opts));
+        assertEquals("Jakarta-Commons-VFS", builder.getUserAgent(opts));
+
+        builder.setConnectionTimeout(opts, 60000);
+        builder.setSoTimeout(opts, 60000);
+        builder.setUserAgent(opts, "foo/bar");
+
+        // ensure changes are visible
+        assertEquals(60000, builder.getConnectionTimeout(opts));
+        assertEquals(60000, builder.getSoTimeout(opts));
+        assertEquals("foo/bar", builder.getUserAgent(opts));
+
+    }
+}

Added: commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4s/test/Http4sGetContentInfoTest.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4s/test/Http4sGetContentInfoTest.java?rev=1845527&view=auto
==============================================================================
--- commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4s/test/Http4sGetContentInfoTest.java (added)
+++ commons/proper/vfs/trunk/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/http4s/test/Http4sGetContentInfoTest.java Fri Nov  2 01:53:29 2018
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs2.provider.http4s.test;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.vfs2.FileContent;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.FileSystemOptions;
+import org.apache.commons.vfs2.VFS;
+import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs2.provider.http4.Http4FileProvider;
+import org.apache.commons.vfs2.provider.http4.Http4FileSystemConfigBuilder;
+import org.apache.commons.vfs2.provider.http4s.Http4sFileProvider;
+import org.junit.Assert;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests VFS-427 NPE on HttpFileObject.getContent().getContentInfo()
+ */
+public class Http4sGetContentInfoTest extends TestCase {
+
+    // TODO: VFS-360 - Remove this manual registration of http4 once http4 becomes part of standard providers.
+    @Override
+    protected void setUp() throws Exception {
+        final DefaultFileSystemManager manager = (DefaultFileSystemManager) VFS.getManager();
+        if (!manager.hasProvider("http4")) {
+            manager.addProvider("http4", new Http4FileProvider());
+        }
+        if (!manager.hasProvider("http4s")) {
+            manager.addProvider("http4s", new Http4sFileProvider());
+        }
+    }
+
+    /**
+     * Tests VFS-427 NPE on HttpFileObject.getContent().getContentInfo().
+     *
+     * @throws FileSystemException thrown when the getContentInfo API fails.
+     * @throws MalformedURLException thrown when the System environment contains an invalid URL for an HTTPS proxy.
+     */
+    @Test
+    public void testGetContentInfo() throws FileSystemException, MalformedURLException {
+        String httpsProxyHost = null;
+        int httpsProxyPort = -1;
+        final String httpsProxy = System.getenv("https_proxy");
+        if (httpsProxy != null) {
+            final URL url = new URL(httpsProxy);
+            httpsProxyHost = url.getHost();
+            httpsProxyPort = url.getPort();
+        }
+        final FileSystemOptions opts;
+        if (httpsProxyHost != null) {
+            opts = new FileSystemOptions();
+            final Http4FileSystemConfigBuilder builder = Http4FileSystemConfigBuilder.getInstance();
+            builder.setProxyHost(opts, httpsProxyHost);
+            if (httpsProxyPort >= 0) {
+                builder.setProxyPort(opts, httpsProxyPort);
+            }
+        } else {
+            opts = null;
+        }
+
+        final FileSystemManager fsManager = VFS.getManager();
+        final FileObject fo = fsManager.resolveFile("http4://www.apache.org/licenses/LICENSE-2.0.txt", opts);
+        final FileContent content = fo.getContent();
+        Assert.assertNotNull(content);
+        // Used to NPE before fix:
+        content.getContentInfo();
+    }
+}

Modified: commons/proper/vfs/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/pom.xml?rev=1845527&r1=1845526&r2=1845527&view=diff
==============================================================================
--- commons/proper/vfs/trunk/pom.xml (original)
+++ commons/proper/vfs/trunk/pom.xml Fri Nov  2 01:53:29 2018
@@ -167,13 +167,13 @@
     <version.checkstyle>2.17</version.checkstyle>
     <!-- make sure bundle plugin has dependency informations for 'optional' -->
     <commons.osgi.excludeDependencies />
-	<commons.osgi.import>
-		org.apache.hadoop.*;resolution:=optional,
-		org.apache.jackrabbit.*;resolution:=optional,
-		org.apache.tools.ant.*;resolution:=optional,
-		org.apache.commons.httpclient.*;resolution:=optional,
-		*
-	</commons.osgi.import>
+    <commons.osgi.import>
+        org.apache.hadoop.*;resolution:=optional,
+        org.apache.jackrabbit.*;resolution:=optional,
+        org.apache.tools.ant.*;resolution:=optional,
+        org.apache.commons.httpclient.*;resolution:=optional,
+        *
+    </commons.osgi.import>
     <!-- Newer versions of clirr throw an NPE building the site -->
     <commons.clirr.version>2.6</commons.clirr.version>
     <!-- Avoid warnings about being unable to find jars during site building -->
@@ -410,6 +410,11 @@
         <version>3.1</version>
       </dependency>
       <dependency>
+        <groupId>org.apache.httpcomponents</groupId>
+        <artifactId>httpclient</artifactId>
+        <version>4.5.6</version>
+      </dependency>
+      <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-compress</artifactId>
         <version>1.18</version>
@@ -515,7 +520,7 @@
       <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpcore-nio</artifactId>
-        <version>4.4.9</version>
+        <version>4.4.10</version>
       </dependency>
       <!-- Test WebDAV with Apache Jackrabbit -->
       <dependency>