1 /* Connection - jar url connection for java.net
2 Copyright (C) 1999, 2002, 2003, 2005 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)
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
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
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 java.io.BufferedInputStream;
42 import java.io.ByteArrayInputStream;
44 import java.io.FileOutputStream;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.net.JarURLConnection;
48 import java.net.MalformedURLException;
49 import java.net.ProtocolException;
51 import java.net.URLConnection;
52 import java.text.SimpleDateFormat;
53 import java.util.Date;
54 import java.util.HashMap;
55 import java.util.Hashtable;
56 import java.util.Locale;
57 import java.util.jar.JarEntry;
58 import java.util.jar.JarFile;
59 import java.util.jar.JarInputStream;
60 import java.util.zip.ZipEntry;
61 import java.util.zip.ZipFile;
64 * This subclass of java.net.JarURLConnection models a URLConnection via
67 * @author Kresten Krab Thorup (krab@gnu.org)
69 public final class Connection extends JarURLConnection
71 private static Hashtable file_cache = new Hashtable();
74 * HTTP-style DateFormat, used to format the last-modified header.
76 private static SimpleDateFormat dateFormat
77 = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'",
78 new Locale ("En", "Us", "Unix"));
80 private JarFile jar_file;
83 * Cached JarURLConnection objects.
85 static HashMap connectionCache = new HashMap();
87 protected Connection(URL url)
88 throws MalformedURLException
93 public synchronized void connect() throws IOException
95 // Call is ignored if already connected.
101 jarFileURLConnection =
102 (URLConnection) connectionCache.get(getJarFileURL());
104 if (jarFileURLConnection == null)
106 jarFileURLConnection = getJarFileURL().openConnection();
107 jarFileURLConnection.setUseCaches(true);
108 jarFileURLConnection.connect();
109 connectionCache.put(getJarFileURL(), jarFileURLConnection);
114 jarFileURLConnection = getJarFileURL().openConnection();
115 jarFileURLConnection.connect();
121 public InputStream getInputStream() throws IOException
127 throw new ProtocolException("Can't open InputStream if doInput is false");
129 if (getEntryName() == null)
131 // This is a JarURLConnection for the entire jar file.
133 InputStream in = new BufferedInputStream
134 (jarFileURLConnection.getInputStream());
135 return new JarInputStream(in);
138 // Reaching this point, we're looking for an entry of a jar file.
140 JarFile jarfile = null;
144 jarfile = getJarFile ();
146 catch (IOException x)
153 // this is the easy way...
154 ZipEntry entry = jarfile.getEntry
155 (gnu.java.net.protocol.file.Connection.unquote(getEntryName()));
158 return jarfile.getInputStream (entry);
164 // If the jar file is not local, ...
165 JarInputStream zis = new JarInputStream(
166 jarFileURLConnection.getInputStream ());
168 String entryName = gnu.java.net.protocol.file.Connection.unquote(getEntryName());
170 // This is hideous, we're doing a linear search...
171 for (ZipEntry entry = zis.getNextEntry();
173 entry = zis.getNextEntry())
175 if (entryName.equals(entry.getName()))
177 int size = (int) entry.getSize();
178 byte[] data = new byte[size];
179 zis.read (data, 0, size);
180 return new ByteArrayInputStream (data);
188 public synchronized JarFile getJarFile() throws IOException
194 throw new ProtocolException("Can't open JarFile if doInput is false");
196 if (jar_file != null)
199 URL jarFileURL = getJarFileURL();
201 if (jarFileURL.getProtocol().equals ("file")
202 && jarFileURL.getHost().equals (""))
206 jar_file = (JarFile) file_cache.get (jarFileURL);
207 if (jar_file == null)
209 jar_file = new JarFile
210 (gnu.java.net.protocol.file.Connection.unquote(jarFileURL.getFile()));
211 file_cache.put (jarFileURL, jar_file);
215 jar_file = new JarFile
216 (gnu.java.net.protocol.file.Connection.unquote(jarFileURL.getFile()));
220 URLConnection urlconn = jarFileURL.openConnection();
221 InputStream is = urlconn.getInputStream();
222 byte[] buf = new byte[4*1024];
223 File f = File.createTempFile("cache", "jar");
224 FileOutputStream fos = new FileOutputStream(f);
226 while ((len = is.read(buf)) != -1)
227 fos.write(buf, 0, len);
229 // Always verify the Manifest, open read only and delete when done.
230 jar_file = new JarFile (f, true,
231 ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
237 public String getHeaderField(String field)
244 if (field.equals("content-type"))
245 return guessContentTypeFromName(getJarEntry().getName());
246 else if (field.equals("content-length"))
247 return Long.toString(getJarEntry().getSize());
248 else if (field.equals("last-modified"))
250 synchronized (dateFormat)
252 return dateFormat.format(new Date(getJarEntry().getTime()));
256 catch (IOException e)
263 public int getContentLength()
270 return (int) getJarEntry().getSize();
272 catch (IOException e)
278 public long getLastModified()
285 return getJarEntry().getTime();
287 catch (IOException e)