Source code: gnu/java/net/protocol/jar/Connection.java
1 /* Connection - jar url connection for java.net
2 Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10
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.
15
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.
20
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.
25
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. */
37
38
39 package gnu.java.net.protocol.jar;
40
41 import java.io.File;
42 import java.io.FileOutputStream;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.net.JarURLConnection;
46 import java.net.MalformedURLException;
47 import java.net.ProtocolException;
48 import java.net.URL;
49 import java.net.URLConnection;
50 import java.util.Hashtable;
51 import java.util.jar.JarEntry;
52 import java.util.jar.JarFile;
53 import java.util.zip.ZipFile;
54
55 /**
56 * This subclass of java.net.JarURLConnection models a URLConnection via
57 * the "jar" protocol.
58 *
59 * @author Kresten Krab Thorup (krab@gnu.org)
60 */
61 public final class Connection extends JarURLConnection
62 {
63 private JarFile jar_file;
64 private JarEntry jar_entry;
65 private URL jar_url;
66
67 public static class JarFileCache
68 {
69 private static Hashtable cache = new Hashtable();
70 private static final int READBUFSIZE = 4*1024;
71
72 public static synchronized JarFile get (URL url) throws IOException
73 {
74 JarFile jf = (JarFile) cache.get (url);
75
76 if (jf != null)
77 return jf;
78
79 if ("file".equals (url.getProtocol()))
80 {
81 File f = new File (url.getFile());
82 jf = new JarFile (f, true, ZipFile.OPEN_READ);
83 }
84 else
85 {
86 URLConnection urlconn = url.openConnection();
87 InputStream is = urlconn.getInputStream();
88 byte[] buf = new byte [READBUFSIZE];
89 File f = File.createTempFile ("cache", "jar");
90 FileOutputStream fos = new FileOutputStream (f);
91 int len = 0;
92
93 while ((len = is.read (buf)) != -1)
94 {
95 fos.write (buf, 0, len);
96 }
97
98 fos.close();
99 // Always verify the Manifest, open read only and delete when done.
100 jf = new JarFile (f, true,
101 ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
102 }
103
104 cache.put (url, jf);
105
106 return jf;
107 }
108 }
109
110 protected Connection(URL url)
111 throws MalformedURLException
112 {
113 super(url);
114 }
115
116 public synchronized void connect() throws IOException
117 {
118 // Call is ignored if already connected.
119 if (connected)
120 return;
121
122 jar_url = getJarFileURL();
123 jar_file = JarFileCache.get (jar_url);
124 String entry_name = getEntryName();
125
126 if (entry_name != null
127 && !entry_name.equals (""))
128 {
129 jar_entry = (JarEntry) jar_file.getEntry (entry_name);
130
131 if(jar_entry == null)
132 throw new IOException ("No entry for " + entry_name + " exists.");
133 }
134
135 connected = true;
136 }
137
138 public InputStream getInputStream() throws IOException
139 {
140 if (!connected)
141 connect();
142
143 if (! doInput)
144 throw new ProtocolException("Can't open InputStream if doInput is false");
145
146 if (jar_entry == null)
147 throw new IOException (jar_url + " couldn't be found.");
148
149 return jar_file.getInputStream (jar_entry);
150 }
151
152 public synchronized JarFile getJarFile() throws IOException
153 {
154 if (!connected)
155 connect();
156
157 if (! doInput)
158 throw new ProtocolException("Can't open JarFile if doInput is false");
159
160 return jar_file;
161 }
162
163 public int getContentLength()
164 {
165 if (!connected)
166 return -1;
167
168 return (int) jar_entry.getSize();
169 }
170 }