libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / java / net / protocol / jar / Handler.java
blob66f0fb6d983a92d0972e0e5ce00302f3d69ee646
1 /* gnu.java.net.protocol.jar.Handler - jar protocol handler for java.net
2 Copyright (C) 1999, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.net.protocol.jar;
41 import gnu.java.lang.CPStringBuilder;
43 import gnu.java.net.URLParseError;
45 import java.io.IOException;
46 import java.net.MalformedURLException;
47 import java.net.URL;
48 import java.net.URLConnection;
49 import java.net.URLStreamHandler;
50 import java.util.ArrayList;
51 import java.util.Iterator;
52 import java.util.StringTokenizer;
54 /**
55 * @author Kresten Krab Thorup (krab@gnu.org)
57 public class Handler extends URLStreamHandler
59 /**
60 * A do nothing constructor
62 public Handler()
66 /**
67 * This method returs a new JarURLConnection for the specified URL
69 * @param url The URL to return a connection for
71 * @return The URLConnection
73 * @exception IOException If an error occurs
75 protected URLConnection openConnection(URL url) throws IOException
77 return new Connection(url);
80 /**
81 * This method overrides URLStreamHandler's for parsing url of protocol "jar"
83 * @param url The URL object in which to store the results
84 * @param url_string The String-ized URL to parse
85 * @param start The position in the string to start scanning from
86 * @param end The position in the string to stop scanning
88 protected void parseURL (URL url, String url_string, int start, int end)
90 // This method does not throw an exception or return a value. Thus our
91 // strategy when we encounter an error in parsing is to return without
92 // doing anything.
93 String file = url.getFile();
95 if (!file.equals(""))
96 { //has context url
97 url_string = url_string.substring (start, end);
98 if (url_string.startsWith("/"))
99 { //url string is an absolute path
100 int idx = file.lastIndexOf ("!/");
102 if (idx < 0)
103 throw new URLParseError("no !/ in spec");
105 file = file.substring (0, idx + 1) + url_string;
107 else if (url_string.length() > 0)
109 int idx = file.lastIndexOf ("/");
110 if (idx == -1) //context path is weird
111 file = "/" + url_string;
112 else if (idx == (file.length() - 1))
113 //just concatenate two parts
114 file = file + url_string;
115 else
116 // according to Java API Documentation, here is a little different
117 // with URLStreamHandler.parseURL
118 // but JDK seems doesn't handle it well
119 file = file.substring(0, idx + 1) + url_string;
122 setURL (url, "jar", url.getHost(), url.getPort(), flat(file), null);
123 return;
126 // Bunches of things should be true. Make sure.
127 if (end < start)
128 return;
129 if (end - start < 2)
130 return;
131 if (start > url_string.length())
132 return;
134 // Skip remains of protocol
135 url_string = url_string.substring (start, end);
137 int jar_stop;
138 if ((jar_stop = url_string.indexOf("!/")) < 0)
139 throw new URLParseError("no !/ in spec");
143 new URL(url_string.substring (0, jar_stop));
145 catch (MalformedURLException e)
147 throw new URLParseError("invalid inner URL: " + e.getMessage());
150 if (!url.getProtocol().equals ("jar") )
151 throw new URLParseError("unexpected protocol " + url.getProtocol());
153 setURL (url, "jar", url.getHost(), url.getPort(), url_string, null);
157 * Makes the given jar url string 'flat' by removing any . and .. from
158 * jar file path because ZipFile entries can only handle flat paths.
159 * Inside jar files '/' is always the path separator.
161 private static String flat(String url_string)
163 int jar_stop = url_string.indexOf("!/");
164 String jar_path = url_string.substring(jar_stop + 1, url_string.length());
166 if (jar_path.indexOf("/.") < 0)
167 return url_string;
169 ArrayList<String> tokens = new ArrayList<String>();
170 StringTokenizer st = new StringTokenizer(jar_path, "/");
171 while (st.hasMoreTokens())
173 String token = st.nextToken();
174 if (token.equals("."))
175 continue;
176 else if (token.equals(".."))
178 if (! tokens.isEmpty())
179 tokens.remove(tokens.size() - 1);
181 else
182 tokens.add(token);
185 CPStringBuilder path = new CPStringBuilder(url_string.length());
186 path.append(url_string.substring(0, jar_stop + 1));
188 Iterator<String> it = tokens.iterator();
189 while (it.hasNext())
190 path.append('/').append(it.next());
192 return path.toString();
196 * This method converts a Jar URL object into a String.
198 * @param url The URL object to convert
200 protected String toExternalForm (URL url)
202 String file = url.getFile();
203 String ref = url.getRef();
205 // return "jar:" + file;
206 // Performance!!:
207 // Do the concatenation manually to avoid resize StringBuffer's
208 // internal buffer. The length of ref is not taken into consideration
209 // as it's a rare path.
210 CPStringBuilder sb = new CPStringBuilder (file.length() + 5);
211 sb.append ("jar:");
212 sb.append (file);
213 if (ref != null)
214 sb.append('#').append(ref);
215 return sb.toString();