Skip to content

Commit e6cd39b

Browse files
committed
Adds URL "jar" protocol
1 parent c14cb37 commit e6cd39b

File tree

8 files changed

+524
-96
lines changed

8 files changed

+524
-96
lines changed
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
/*
2+
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package java.net;
27+
28+
import java.io.IOException;
29+
import java.util.jar.JarFile;
30+
import java.util.jar.JarEntry;
31+
import java.util.jar.Attributes;
32+
import java.util.jar.Manifest;
33+
import sun.net.www.ParseUtil;
34+
35+
/**
36+
* A URL Connection to a Java ARchive (JAR) file or an entry in a JAR
37+
* file.
38+
*
39+
* <p>The syntax of a JAR URL is:
40+
*
41+
* <pre>
42+
* jar:&lt;url&gt;!/{entry}
43+
* </pre>
44+
*
45+
* <p>for example:
46+
*
47+
* <p>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class}
48+
*
49+
* <p>Jar URLs should be used to refer to a JAR file or entries in
50+
* a JAR file. The example above is a JAR URL which refers to a JAR
51+
* entry. If the entry name is omitted, the URL refers to the whole
52+
* JAR file:
53+
*
54+
* {@code jar:http://www.foo.com/bar/baz.jar!/}
55+
*
56+
* <p>Users should cast the generic URLConnection to a
57+
* JarURLConnection when they know that the URL they created is a JAR
58+
* URL, and they need JAR-specific functionality. For example:
59+
*
60+
* <pre>
61+
* URL url = new URL("jar:file:/home/duke/duke.jar!/");
62+
* JarURLConnection jarConnection = (JarURLConnection)url.openConnection();
63+
* Manifest manifest = jarConnection.getManifest();
64+
* </pre>
65+
*
66+
* <p>JarURLConnection instances can only be used to read from JAR files.
67+
* It is not possible to get a {@link java.io.OutputStream} to modify or write
68+
* to the underlying JAR file using this class.
69+
* <p>Examples:
70+
*
71+
* <dl>
72+
*
73+
* <dt>A Jar entry
74+
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class}
75+
*
76+
* <dt>A Jar file
77+
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/}
78+
*
79+
* <dt>A Jar directory
80+
* <dd>{@code jar:http://www.foo.com/bar/baz.jar!/COM/foo/}
81+
*
82+
* </dl>
83+
*
84+
* <p>{@code !/} is referred to as the <em>separator</em>.
85+
*
86+
* <p>When constructing a JAR url via {@code new URL(context, spec)},
87+
* the following rules apply:
88+
*
89+
* <ul>
90+
*
91+
* <li>if there is no context URL and the specification passed to the
92+
* URL constructor doesn't contain a separator, the URL is considered
93+
* to refer to a JarFile.
94+
*
95+
* <li>if there is a context URL, the context URL is assumed to refer
96+
* to a JAR file or a Jar directory.
97+
*
98+
* <li>if the specification begins with a '/', the Jar directory is
99+
* ignored, and the spec is considered to be at the root of the Jar
100+
* file.
101+
*
102+
* <p>Examples:
103+
*
104+
* <dl>
105+
*
106+
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/</b>,
107+
* spec:<b>baz/entry.txt</b>
108+
*
109+
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/baz/entry.txt</b>
110+
*
111+
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/baz</b>,
112+
* spec:<b>entry.txt</b>
113+
*
114+
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/baz/entry.txt</b>
115+
*
116+
* <dt>context: <b>jar:http://www.foo.com/bar/jar.jar!/baz</b>,
117+
* spec:<b>/entry.txt</b>
118+
*
119+
* <dd>url:<b>jar:http://www.foo.com/bar/jar.jar!/entry.txt</b>
120+
*
121+
* </dl>
122+
*
123+
* </ul>
124+
*
125+
* @see java.net.URL
126+
* @see java.net.URLConnection
127+
*
128+
* @see java.util.jar.JarFile
129+
* @see java.util.jar.JarInputStream
130+
* @see java.util.jar.Manifest
131+
* @see java.util.zip.ZipEntry
132+
*
133+
* @author Benjamin Renaud
134+
* @since 1.2
135+
*/
136+
public abstract class JarURLConnection extends URLConnection {
137+
138+
private URL jarFileURL;
139+
private String entryName;
140+
141+
/**
142+
* The connection to the JAR file URL, if the connection has been
143+
* initiated. This should be set by connect.
144+
*/
145+
protected URLConnection jarFileURLConnection;
146+
147+
/**
148+
* Creates the new JarURLConnection to the specified URL.
149+
* @param url the URL
150+
* @throws MalformedURLException if no legal protocol
151+
* could be found in a specification string or the
152+
* string could not be parsed.
153+
*/
154+
155+
protected JarURLConnection(URL url) throws MalformedURLException {
156+
super(url);
157+
parseSpecs(url);
158+
}
159+
160+
/* get the specs for a given url out of the cache, and compute and
161+
* cache them if they're not there.
162+
*/
163+
private void parseSpecs(URL url) throws MalformedURLException {
164+
String spec = url.getFile();
165+
166+
int separator = spec.indexOf("!/");
167+
/*
168+
* REMIND: we don't handle nested JAR URLs
169+
*/
170+
if (separator == -1) {
171+
throw new MalformedURLException("no !/ found in url spec:" + spec);
172+
}
173+
174+
jarFileURL = new URL(spec.substring(0, separator++));
175+
entryName = null;
176+
177+
/* if ! is the last letter of the innerURL, entryName is null */
178+
if (++separator != spec.length()) {
179+
entryName = spec.substring(separator, spec.length());
180+
entryName = ParseUtil.decode (entryName);
181+
}
182+
}
183+
184+
/**
185+
* Returns the URL for the Jar file for this connection.
186+
*
187+
* @return the URL for the Jar file for this connection.
188+
*/
189+
public URL getJarFileURL() {
190+
return jarFileURL;
191+
}
192+
193+
/**
194+
* Return the entry name for this connection. This method
195+
* returns null if the JAR file URL corresponding to this
196+
* connection points to a JAR file and not a JAR file entry.
197+
*
198+
* @return the entry name for this connection, if any.
199+
*/
200+
public String getEntryName() {
201+
return entryName;
202+
}
203+
204+
/**
205+
* Return the JAR file for this connection.
206+
*
207+
* @return the JAR file for this connection. If the connection is
208+
* a connection to an entry of a JAR file, the JAR file object is
209+
* returned
210+
*
211+
* @exception IOException if an IOException occurs while trying to
212+
* connect to the JAR file for this connection.
213+
*
214+
* @see #connect
215+
*/
216+
public abstract JarFile getJarFile() throws IOException;
217+
218+
/**
219+
* Returns the Manifest for this connection, or null if none.
220+
*
221+
* @return the manifest object corresponding to the JAR file object
222+
* for this connection.
223+
*
224+
* @exception IOException if getting the JAR file for this
225+
* connection causes an IOException to be thrown.
226+
*
227+
* @see #getJarFile
228+
*/
229+
public Manifest getManifest() throws IOException {
230+
return getJarFile().getManifest();
231+
}
232+
233+
/**
234+
* Return the JAR entry object for this connection, if any. This
235+
* method returns null if the JAR file URL corresponding to this
236+
* connection points to a JAR file and not a JAR file entry.
237+
*
238+
* @return the JAR entry object for this connection, or null if
239+
* the JAR URL for this connection points to a JAR file.
240+
*
241+
* @exception IOException if getting the JAR file for this
242+
* connection causes an IOException to be thrown.
243+
*
244+
* @see #getJarFile
245+
* @see #getJarEntry
246+
*/
247+
public JarEntry getJarEntry() throws IOException {
248+
return getJarFile().getJarEntry(entryName);
249+
}
250+
251+
/**
252+
* Return the Attributes object for this connection if the URL
253+
* for it points to a JAR file entry, null otherwise.
254+
*
255+
* @return the Attributes object for this connection if the URL
256+
* for it points to a JAR file entry, null otherwise.
257+
*
258+
* @exception IOException if getting the JAR entry causes an
259+
* IOException to be thrown.
260+
*
261+
* @see #getJarEntry
262+
*/
263+
public Attributes getAttributes() throws IOException {
264+
JarEntry e = getJarEntry();
265+
return e != null ? e.getAttributes() : null;
266+
}
267+
268+
/**
269+
* Returns the main Attributes for the JAR file for this
270+
* connection.
271+
*
272+
* @return the main Attributes for the JAR file for this
273+
* connection.
274+
*
275+
* @exception IOException if getting the manifest causes an
276+
* IOException to be thrown.
277+
*
278+
* @see #getJarFile
279+
* @see #getManifest
280+
*/
281+
public Attributes getMainAttributes() throws IOException {
282+
Manifest man = getManifest();
283+
return man != null ? man.getMainAttributes() : null;
284+
}
285+
286+
/**
287+
* Return the Certificate object for this connection if the URL
288+
* for it points to a JAR file entry, null otherwise. This method
289+
* can only be called once
290+
* the connection has been completely verified by reading
291+
* from the input stream until the end of the stream has been
292+
* reached. Otherwise, this method will return {@code null}
293+
*
294+
* @return the Certificate object for this connection if the URL
295+
* for it points to a JAR file entry, null otherwise.
296+
*
297+
* @exception IOException if getting the JAR entry causes an
298+
* IOException to be thrown.
299+
*
300+
* @see #getJarEntry
301+
*/
302+
public java.security.cert.Certificate[] getCertificates()
303+
throws IOException
304+
{
305+
JarEntry e = getJarEntry();
306+
return e != null ? e.getCertificates() : null;
307+
}
308+
309+
}

sources/net.sf.j2s.java.core/src/java/net/URL.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Hashtable;
3737

3838
import javajs.util.AjaxURLConnection;
39+
import javajs.util.AjaxURLStreamHandlerFactory;
3940

4041
/**
4142
* Class <code>URL</code> represents a Uniform Resource Locator, a pointer to a
@@ -1178,7 +1179,7 @@ static URLStreamHandler getURLStreamHandler(String protocol) {
11781179
if (秘factory == null) {
11791180
// SwingJS -- we always use javajs.util.AjaxURLStreamHandlerFactory
11801181
try {
1181-
URL.setURLStreamHandlerFactory((URLStreamHandlerFactory) Class.forName("javajs.util.AjaxURLStreamHandlerFactory").newInstance());
1182+
URL.setURLStreamHandlerFactory(new AjaxURLStreamHandlerFactory());
11821183
} catch (Exception e) {
11831184

11841185
}

sources/net.sf.j2s.java.core/src/javajs/util/AjaxURLConnection.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.Map.Entry;
1616

1717
import javajs.api.js.J2SObjectInterface;
18+
import swingjs.JSUtil;
1819

1920
/**
2021
*
@@ -138,7 +139,9 @@ private Object doAjax(boolean isBinary) {
138139
*/
139140
}
140141
String myURL = url.toString();
141-
142+
if (myURL.startsWith("file:")) {
143+
myURL = JSUtil.J2S.getResourcePath("", true) + myURL.substring(5);
144+
}
142145

143146
Object result = J2S.doAjax(myURL, postOut, bytesOut, info);
144147
boolean isEmpty = false;

sources/net.sf.j2s.java.core/src/javajs/util/AjaxURLStreamHandler.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package javajs.util;
22

33
import java.io.IOException;
4+
import java.net.JarURLConnection;
45
import java.net.URL;
56
import java.net.URLConnection;
67
import java.net.URLStreamHandler;
@@ -23,6 +24,8 @@ public AjaxURLStreamHandler(String protocol) {
2324

2425
@Override
2526
protected URLConnection openConnection(URL url) throws IOException {
27+
if (protocol.equals("jar"))
28+
return new JSJarURLConnection(url);
2629
return AjaxURLConnection.newConnection(url);
2730
}
2831
}

sources/net.sf.j2s.java.core/src/javajs/util/AjaxURLStreamHandlerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ public AjaxURLStreamHandlerFactory() {
2323
@Override
2424
public URLStreamHandler createURLStreamHandler(String protocol) {
2525
AjaxURLStreamHandler fac = htFactories.get(protocol);
26-
if (fac == null)
26+
if (fac == null) {
2727
htFactories.put(protocol, fac = new AjaxURLStreamHandler(protocol));
28+
}
2829
return (fac.protocol == null ? null : fac);
2930
}
3031

0 commit comments

Comments
 (0)