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:<url>!/{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+ }
0 commit comments