KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > util > ParsedURLDefaultProtocolHandler


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    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  */

18 package org.apache.batik.util;
19
20 import java.net.MalformedURLException JavaDoc;
21 import java.net.URL JavaDoc;
22
23
24 /**
25  * The default protocol handler this handles the most common
26  * protocols, such as 'file' 'http' 'ftp'.
27  * The parsing should be general enought to support most
28  * 'normal' URL formats, so in many cases
29  *
30  * @author <a HREF="mailto:deweese@apache.org">Thomas DeWeese</a>
31  * @version $Id: ParsedURLDefaultProtocolHandler.java,v 1.17 2005/03/27 08:58:36 cam Exp $
32  */

33 public class ParsedURLDefaultProtocolHandler
34     extends AbstractParsedURLProtocolHandler {
35
36     /**
37      * Default constructor sets no protocol so this becomes
38      * default handler.
39      */

40     public ParsedURLDefaultProtocolHandler() {
41         super(null);
42     }
43
44     /**
45      * Subclass constructor allows subclasses to provide protocol,
46      * to be handled.
47      */

48     protected ParsedURLDefaultProtocolHandler(String JavaDoc protocol) {
49         super(protocol);
50     }
51
52     /**
53      * Subclasses can override these method to construct alternate
54      * subclasses of ParsedURLData.
55      */

56     protected ParsedURLData constructParsedURLData() {
57         return new ParsedURLData();
58     }
59
60     /**
61      * Subclasses can override these method to construct alternate
62      * subclasses of ParsedURLData.
63      * @param url the java.net.URL class we reference.
64      */

65     protected ParsedURLData constructParsedURLData(URL JavaDoc url) {
66         return new ParsedURLData(url);
67     }
68
69     /**
70      * Parses the string and returns the results of parsing in the
71      * ParsedURLData object.
72      * @param urlStr the string to parse as a URL.
73      */

74     public ParsedURLData parseURL(String JavaDoc urlStr) {
75         try {
76             URL JavaDoc url = new URL JavaDoc(urlStr);
77             // System.err.println("System Parse: " + urlStr);
78
return constructParsedURLData(url);
79         } catch (MalformedURLException JavaDoc mue) {
80             // Built in URL wouldn't take it...
81
// mue.printStackTrace();
82
}
83
84         // new Exception("Custom Parse: " + urlStr).printStackTrace();
85
// System.err.println("Custom Parse: " + urlStr);
86

87         ParsedURLData ret = constructParsedURLData();
88
89         if (urlStr == null) return ret;
90
91         int pidx=0, idx;
92         int len = urlStr.length();
93
94         // Pull fragement id off first...
95
idx = urlStr.indexOf('#');
96         ret.ref = null;
97         if (idx != -1) {
98             if (idx+1 < len)
99                 ret.ref = urlStr.substring(idx+1);
100             urlStr = urlStr.substring(0,idx);
101             len = urlStr.length();
102         }
103
104         if (len == 0)
105             return ret;
106
107         // Protocol is only allowed to include -+.a-zA-Z
108
// So as soon as we hit something else we know we
109
// are done (if it is a ':' then we have protocol otherwise
110
// we don't.
111
idx = 0;
112         char ch = urlStr.charAt(idx);
113         while ((ch == '-') ||
114                (ch == '+') ||
115                (ch == '.') ||
116                ((ch >= 'a') && (ch <= 'z')) ||
117                ((ch >= 'A') && (ch <= 'Z'))) {
118             idx++;
119             if (idx == len) {
120                 ch=0;
121                 break;
122             }
123             ch = urlStr.charAt(idx);
124         }
125
126         if (ch == ':') {
127             // Has a protocol spec...
128
ret.protocol = urlStr.substring(pidx, idx).toLowerCase();
129             pidx = idx+1; // Skip ':'
130
}
131
132         // See if we have host/port spec.
133
idx = urlStr.indexOf('/');
134         if ((idx == -1) || ((pidx+2<len) &&
135                             (urlStr.charAt(pidx) == '/') &&
136                             (urlStr.charAt(pidx+1) == '/'))) {
137             // No slashes (apache.org) or a double slash
138
// (//apache.org/....) so
139
// we should have host[:port] before next slash.
140
if (idx != -1)
141                 pidx+=2; // Skip double slash...
142

143             idx = urlStr.indexOf('/', pidx); // find end of host:Port spec
144
String JavaDoc hostPort;
145             if (idx == -1)
146                 // Just host and port nothing following...
147
hostPort = urlStr.substring(pidx);
148             else
149                 // Path spec follows...
150
hostPort = urlStr.substring(pidx, idx);
151
152             int hidx = idx; // Remember location of '/'
153

154             // pull apart host and port number...
155
idx = hostPort.indexOf(':');
156             ret.port = -1;
157             if (idx == -1) {
158                 // Just Host...
159
if (hostPort.length() == 0)
160                     ret.host = null;
161                 else
162                     ret.host = hostPort;
163             } else {
164                 // Host and port
165
if (idx == 0) ret.host = null;
166                 else ret.host = hostPort.substring(0,idx);
167
168                 if (idx+1 < hostPort.length()) {
169                     String JavaDoc portStr = hostPort.substring(idx+1);
170                     try {
171                         ret.port = Integer.parseInt(portStr);
172                     } catch (NumberFormatException JavaDoc nfe) {
173                         // bad port leave as '-1'
174
}
175                 }
176             }
177             if (((ret.host == null) || (ret.host.indexOf('.') == -1)) &&
178                 (ret.port == -1))
179                 // no '.' in a host spec??? and no port, probably
180
// just a path.
181
ret.host = null;
182             else
183                 pidx = hidx;
184         }
185
186         if ((pidx == -1) || (pidx >= len)) return ret; // Nothing follows
187

188         ret.path = urlStr.substring(pidx);
189         return ret;
190     }
191
192     public static String JavaDoc unescapeStr(String JavaDoc str) {
193         int idx = str.indexOf('%');
194         if (idx == -1) return str; // quick out..
195

196         int prev=0;
197         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
198         while (idx != -1) {
199             if (idx != prev)
200                 ret.append(str.substring(prev, idx));
201
202             if (idx+2 >= str.length()) break;
203             prev = idx+3;
204             idx = str.indexOf('%', prev);
205
206             int ch1 = charToHex(str.charAt(idx+1));
207             int ch2 = charToHex(str.charAt(idx+1));
208             if ((ch1 == -1) || (ch2==-1)) continue;
209             ret.append((char)(ch1<<4 | ch2));
210         }
211
212         return ret.toString();
213     }
214
215     public static int charToHex(int ch) {
216         switch(ch) {
217         case '0': case '1': case '2': case '3': case '4':
218         case '5': case '6': case '7': case '8': case '9':
219             return ch-'0';
220         case 'a': case 'A': return 10;
221         case 'b': case 'B': return 11;
222         case 'c': case 'C': return 12;
223         case 'd': case 'D': return 13;
224         case 'e': case 'E': return 14;
225         case 'f': case 'F': return 15;
226         default: return -1;
227         }
228     }
229
230     /**
231      * Parses the string as a sub URL of baseURL, and returns the
232      * results of parsing in the ParsedURLData object.
233      * @param baseURL the base url for parsing.
234      * @param urlStr the string to parse as a URL.
235      */

236     public ParsedURLData parseURL(ParsedURL baseURL, String JavaDoc urlStr) {
237         // Reference to same document (including fragment, and query).
238
if (urlStr.length() == 0)
239             return baseURL.data;
240
241         // System.err.println("Base: " + baseURL + "\n" +
242
// "Sub: " + urlStr);
243

244         int idx = 0, len = urlStr.length();
245         if (len == 0) return baseURL.data;
246
247         // Protocol is only allowed to include -+.a-zA-Z
248
// So as soon as we hit something else we know we
249
// are done (if it is a ':' then we have protocol otherwise
250
// we don't.
251
char ch = urlStr.charAt(idx);
252         while ((ch == '-') ||
253                (ch == '+') ||
254                (ch == '.') ||
255                ((ch >= 'a') && (ch <= 'z')) ||
256                ((ch >= 'A') && (ch <= 'Z'))) {
257             idx++;
258             if (idx == len) {
259                 ch=0;
260                 break;
261             }
262             ch = urlStr.charAt(idx);
263         }
264         String JavaDoc protocol = null;
265         if (ch == ':') {
266             // Has a protocol spec...
267
protocol = urlStr.substring(0, idx).toLowerCase();
268         }
269
270         if (protocol != null) {
271             // Temporary if we have a protocol then assume absolute
272
// URL. Technically this is the correct handling but much
273
// software supports relative URLs with a protocol that
274
// matches the base URL's protocol.
275
// if (true)
276
// return parseURL(urlStr);
277
if (!protocol.equals(baseURL.getProtocol()))
278                 // Different protocols, assume absolute URL ignore base...
279
return parseURL(urlStr);
280
281             // Same protocols, if char after ':' is a '/' then it's
282
// still absolute...
283
idx++;
284             if (idx == urlStr.length())
285                 // Just a Protocol???
286
return parseURL(urlStr);
287
288             if (urlStr.charAt(idx) == '/')
289                 // Absolute URL...
290
return parseURL(urlStr);
291
292             // Still relative just drop the protocol (we will pick it
293
// back up from the baseURL later...).
294
urlStr = urlStr.substring(idx);
295         }
296
297         if (urlStr.startsWith("/")) {
298             if ((urlStr.length() > 1) &&
299                 (urlStr.charAt(1) == '/')) {
300                 // Relative but only uses protocol from base
301
return parseURL(baseURL.getProtocol() + ":" + urlStr);
302             }
303             // Relative 'absolute' path, uses protocol and authority
304
// (host) from base
305
return parseURL(baseURL.getPortStr() + urlStr);
306         }
307
308         if (urlStr.startsWith("#")) {
309             String JavaDoc base = baseURL.getPortStr();
310             if (baseURL.getPath() != null) base += baseURL.getPath();
311             return parseURL(base + urlStr);
312         }
313
314         String JavaDoc path = baseURL.getPath();
315         // No path? well we will treat this as being relative to it's self.
316
if (path == null) path = "";
317         idx = path.lastIndexOf('/');
318         if (idx == -1)
319             // baseURL is just a filename (in current dir) so use current dir
320
// as base of new URL.
321
path = "";
322         else
323             path = path.substring(0,idx+1);
324         
325         // System.err.println("Base Path: " + path);
326
// System.err.println("Base PortStr: " + baseURL.getPortStr());
327
return parseURL(baseURL.getPortStr() + path + urlStr);
328     }
329 }
330
331
Popular Tags