1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.provider;
18
19 import org.apache.commons.vfs.FileName;
20 import org.apache.commons.vfs.FileSystemException;
21 import org.apache.commons.vfs.FileType;
22
23 /***
24 * Implementation for any url based filesystem.<br />
25 * Parses the url into user/password/host/port/path<br />
26 * Does not handle a query string (after ?)
27 *
28 * @author imario@apache.org
29 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
30 * @see URLFileNameParser URLFileNameParser for the implementation which also handles the query string too
31 */
32 public class HostFileNameParser extends AbstractFileNameParser
33 {
34 private final int defaultPort;
35
36 public HostFileNameParser(final int defaultPort)
37 {
38 this.defaultPort = defaultPort;
39 }
40
41 public int getDefaultPort()
42 {
43 return defaultPort;
44 }
45
46 public boolean encodeCharacter(char ch)
47 {
48 return super.encodeCharacter(ch);
49 }
50
51 public FileName parseUri(final VfsComponentContext context, FileName base, final String filename) throws FileSystemException
52 {
53
54 final StringBuffer name = new StringBuffer();
55
56
57 final Authority auth = extractToPath(filename, name);
58
59
60 UriParser.canonicalizePath(name, 0, name.length(), this);
61 UriParser.fixSeparators(name);
62 FileType fileType = UriParser.normalisePath(name);
63 final String path = name.toString();
64
65 return new GenericFileName(
66 auth.scheme,
67 auth.hostName,
68 auth.port,
69 defaultPort,
70 auth.userName,
71 auth.password,
72 path,
73 fileType);
74 }
75
76 /***
77 * Extracts the scheme, userinfo, hostname and port components of a
78 * generic URI.
79 *
80 * @param uri The absolute URI to parse.
81 * @param name Used to return the remainder of the URI.
82 */
83 protected Authority extractToPath(final String uri,
84 final StringBuffer name)
85 throws FileSystemException
86 {
87 final Authority auth = new Authority();
88
89
90 auth.scheme = UriParser.extractScheme(uri, name);
91
92
93 if (name.length() < 2 || name.charAt(0) != '/' || name.charAt(1) != '/')
94 {
95 throw new FileSystemException("vfs.provider/missing-double-slashes.error", uri);
96 }
97 name.delete(0, 2);
98
99
100 final String userInfo = extractUserInfo(name);
101 final String userName;
102 final String password;
103 if (userInfo != null)
104 {
105 int idx = userInfo.indexOf(':');
106 if (idx == -1)
107 {
108 userName = userInfo;
109 password = null;
110 }
111 else
112 {
113 userName = userInfo.substring(0, idx);
114 password = userInfo.substring(idx + 1);
115 }
116 }
117 else
118 {
119 userName = null;
120 password = null;
121 }
122 auth.userName = UriParser.decode(userName);
123 auth.password = UriParser.decode(password);
124
125
126 final String hostName = extractHostName(name);
127 if (hostName == null)
128 {
129 throw new FileSystemException("vfs.provider/missing-hostname.error", uri);
130 }
131 auth.hostName = hostName.toLowerCase();
132
133
134 auth.port = extractPort(name, uri);
135
136
137 if (name.length() > 0 && name.charAt(0) != '/')
138 {
139 throw new FileSystemException("vfs.provider/missing-hostname-path-sep.error", uri);
140 }
141
142 return auth;
143 }
144
145 /***
146 * Extracts the user info from a URI. The scheme:// part has been removed
147 * already.
148 */
149 protected String extractUserInfo(final StringBuffer name)
150 {
151 final int maxlen = name.length();
152 for (int pos = 0; pos < maxlen; pos++)
153 {
154 final char ch = name.charAt(pos);
155 if (ch == '@')
156 {
157
158 String userInfo = name.substring(0, pos);
159 name.delete(0, pos + 1);
160 return userInfo;
161 }
162 if (ch == '/' || ch == '?')
163 {
164
165 break;
166 }
167 }
168
169
170 return null;
171 }
172
173 /***
174 * Extracts the hostname from a URI. The scheme://userinfo@ part has
175 * been removed.
176 */
177 protected String extractHostName(final StringBuffer name)
178 {
179 final int maxlen = name.length();
180 int pos = 0;
181 for (; pos < maxlen; pos++)
182 {
183 final char ch = name.charAt(pos);
184 if (ch == '/' || ch == ';' || ch == '?' || ch == ':'
185 || ch == '@' || ch == '&' || ch == '=' || ch == '+'
186 || ch == '$' || ch == ',')
187 {
188 break;
189 }
190 }
191 if (pos == 0)
192 {
193 return null;
194 }
195
196 final String hostname = name.substring(0, pos);
197 name.delete(0, pos);
198 return hostname;
199 }
200
201 /***
202 * Extracts the port from a URI. The scheme://userinfo@hostname
203 * part has been removed.
204 *
205 * @return The port, or -1 if the URI does not contain a port.
206 */
207 protected int extractPort(final StringBuffer name, final String uri) throws FileSystemException
208 {
209 if (name.length() < 1 || name.charAt(0) != ':')
210 {
211 return -1;
212 }
213
214 final int maxlen = name.length();
215 int pos = 1;
216 for (; pos < maxlen; pos++)
217 {
218 final char ch = name.charAt(pos);
219 if (ch < '0' || ch > '9')
220 {
221 break;
222 }
223 }
224
225 final String port = name.substring(1, pos);
226 name.delete(0, pos);
227 if (port.length() == 0)
228 {
229 throw new FileSystemException("vfs.provider/missing-port.error", uri);
230 }
231
232 return Integer.parseInt(port);
233 }
234
235 /***
236 * Parsed authority info (scheme, hostname, userinfo, port)
237 */
238 protected static class Authority
239 {
240 public String scheme;
241 public String hostName;
242 public String userName;
243 public String password;
244 public int port;
245 }
246 }