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.url;
18  
19  import org.apache.commons.vfs2.FileName;
20  import org.apache.commons.vfs2.FileSystemException;
21  import org.apache.commons.vfs2.provider.AbstractFileNameParser;
22  import org.apache.commons.vfs2.provider.URLFileName;
23  import org.apache.commons.vfs2.provider.URLFileNameParser;
24  import org.apache.commons.vfs2.provider.VfsComponentContext;
25  import org.apache.commons.vfs2.provider.local.GenericFileNameParser;
26  
27  /**
28   * Implementation for any java.net.url based file system.
29   * <p>
30   * Composite of URLFilenameParser and GenericFilenameParser
31   */
32  public class UrlFileNameParser extends AbstractFileNameParser {
33  
34      private final URLFileNameParser urlFileNameParser = new URLFileNameParser(80);
35      private final GenericFileNameParser genericFileNameParser = new GenericFileNameParser();
36  
37      /**
38       * Constructs a new instance.
39       */
40      public UrlFileNameParser() {
41      }
42  
43      /**
44       * This method counts the slashes after the scheme.
45       *
46       * @param fileName The file name.
47       * @return number of slashes
48       */
49      protected int countSlashes(final String fileName) {
50          int state = 0;
51          int nuofSlash = 0;
52          for (int pos = 0; pos < fileName.length(); pos++) {
53              final char c = fileName.charAt(pos);
54              if (state == 0) {
55                  if (c >= 'a' && c <= 'z') {
56                      continue;
57                  }
58                  if (c == ':') {
59                      state++;
60                      continue;
61                  }
62              } else if (state == 1) {
63                  if (c != '/') {
64                      return nuofSlash;
65                  }
66                  nuofSlash++;
67              }
68          }
69          return nuofSlash;
70      }
71  
72      @Override
73      public boolean encodeCharacter(final char ch) {
74          return super.encodeCharacter(ch) || ch == '?';
75      }
76  
77      /**
78       * Guess if the given file name is a URL with host or not.
79       * <p>
80       * VFS treats such URLs differently.
81       * </p>
82       * <p>
83       * A file name is URL-based if the base is a {@code URLFileName} or there are only 2 slashes after the scheme. e.g:
84       * {@code http://host/path}, {@code file:/path/to/file}, {@code file:///path/to/file}.
85       * </p>
86       *
87       * @param base The file name is relative to this base.
88       * @param fileName The file name.
89       * @return true if file name contains two slashes or base was URLFileName.
90       */
91      protected boolean isUrlBased(final FileName base, final String fileName) {
92          if (base instanceof URLFileName) {
93              return true;
94          }
95  
96          return countSlashes(fileName) == 2;
97      }
98  
99      /**
100      * Parse a URI.
101      *
102      * @param context The component context.
103      * @param base The base FileName.
104      * @param uri The target file name.
105      * @return The FileName.
106      * @throws FileSystemException if an error occurs
107      */
108     @Override
109     public FileName parseUri(final VfsComponentContext context, final FileName base, final String uri)
110             throws FileSystemException {
111         if (isUrlBased(base, uri)) {
112             return urlFileNameParser.parseUri(context, base, uri);
113         }
114         return genericFileNameParser.parseUri(context, base, uri);
115     }
116 }