OSDN Git Service

* include/java-interp.h (_Jv_InterpMethod::dump_object): Removed
[pf3gnuchains/gcc-fork.git] / libjava / 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.BufferedInputStream;
42 import java.io.ByteArrayInputStream;
43 import java.io.File;
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;
50 import java.net.URL;
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;
62
63 /**
64  * This subclass of java.net.JarURLConnection models a URLConnection via
65  * the "jar" protocol.
66  *
67  * @author Kresten Krab Thorup (krab@gnu.org)
68  */
69 public final class Connection extends JarURLConnection
70 {
71   private static Hashtable file_cache = new Hashtable();
72
73   /**
74    * HTTP-style DateFormat, used to format the last-modified header.
75    */
76   private static SimpleDateFormat dateFormat
77     = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'",
78                            new Locale ("En", "Us", "Unix"));
79
80   private JarFile jar_file;
81
82   /**
83    * Cached JarURLConnection objects.
84    */
85   static HashMap connectionCache = new HashMap();
86
87   protected Connection(URL url)
88     throws MalformedURLException
89   {
90     super(url);
91   }
92
93   public synchronized void connect() throws IOException
94   {
95     // Call is ignored if already connected.
96     if (connected)
97       return;
98
99     if (getUseCaches())
100       {
101         jarFileURLConnection =
102           (URLConnection) connectionCache.get(getJarFileURL());
103
104         if (jarFileURLConnection == null)
105           {
106             jarFileURLConnection = getJarFileURL().openConnection();
107             jarFileURLConnection.setUseCaches(true);
108             jarFileURLConnection.connect();
109             connectionCache.put(getJarFileURL(), jarFileURLConnection);
110           }
111       }
112     else
113       {
114         jarFileURLConnection = getJarFileURL().openConnection();
115         jarFileURLConnection.connect();
116       }
117
118     connected = true;
119   }
120
121   public InputStream getInputStream() throws IOException
122   {
123     if (!connected)
124       connect();
125
126     if (! doInput)
127       throw new ProtocolException("Can't open InputStream if doInput is false");
128
129     if (getEntryName() == null)
130       {
131         // This is a JarURLConnection for the entire jar file.  
132
133         InputStream in = new BufferedInputStream
134           (jarFileURLConnection.getInputStream());
135         return new JarInputStream(in);
136       }
137
138     // Reaching this point, we're looking for an entry of a jar file.
139
140     JarFile jarfile = null;
141
142     try
143       {
144         jarfile = getJarFile ();
145       }
146     catch (IOException x)
147       {
148         /* ignore */
149       }
150     
151     if (jarfile != null)
152       {
153         // this is the easy way...
154         ZipEntry entry = jarfile.getEntry
155           (gnu.java.net.protocol.file.Connection.unquote(getEntryName()));
156         
157         if (entry != null)
158           return jarfile.getInputStream (entry);
159         else
160           return null;
161       }
162     else
163       {
164         // If the jar file is not local, ...
165         JarInputStream zis = new JarInputStream(
166                         jarFileURLConnection.getInputStream ());
167
168         String entryName = gnu.java.net.protocol.file.Connection.unquote(getEntryName());
169
170         // This is hideous, we're doing a linear search...
171         for (ZipEntry entry = zis.getNextEntry(); 
172              entry != null; 
173              entry = zis.getNextEntry())
174           {
175             if (entryName.equals(entry.getName()))
176               {
177                 int size = (int) entry.getSize();
178                 byte[] data = new byte[size];
179                 zis.read (data, 0, size);
180                 return new ByteArrayInputStream (data);
181               }
182           }
183       }
184
185     return null;
186   }
187
188   public synchronized JarFile getJarFile() throws IOException
189   {
190     if (!connected)
191       connect();
192
193     if (! doInput)
194       throw new ProtocolException("Can't open JarFile if doInput is false");
195
196     if (jar_file != null)
197       return jar_file;
198
199     URL jarFileURL = getJarFileURL();
200
201     if (jarFileURL.getProtocol().equals ("file")
202         && jarFileURL.getHost().equals (""))
203       {
204         if (getUseCaches())
205           {
206             jar_file = (JarFile) file_cache.get (jarFileURL);
207             if (jar_file == null)
208               {
209                 jar_file = new JarFile 
210                   (gnu.java.net.protocol.file.Connection.unquote(jarFileURL.getFile()));
211                 file_cache.put (jarFileURL, jar_file);
212               }
213           }
214         else
215           jar_file = new JarFile 
216             (gnu.java.net.protocol.file.Connection.unquote(jarFileURL.getFile()));
217       }
218     else
219       {
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);
225         int len = 0;
226         while ((len = is.read(buf)) != -1)
227           fos.write(buf, 0, len);
228         fos.close();
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);
232       }
233
234     return jar_file;
235   }
236
237   public String getHeaderField(String field)
238   {
239     try
240       {
241         if (!connected)
242           connect();
243
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"))
249           {
250             synchronized (dateFormat)
251               {
252                 return dateFormat.format(new Date(getJarEntry().getTime()));
253               }
254           }
255       }
256     catch (IOException e)
257       {
258         // Fall through.
259       }
260     return null;
261   }
262
263   public int getContentLength()
264   {
265     if (!connected)
266       return -1;
267
268     try
269       {
270         return (int) getJarEntry().getSize();
271       }
272     catch (IOException e)
273       {
274         return -1;
275       }
276   }
277
278   public long getLastModified()
279   {
280     if (!connected)
281       return -1;
282
283     try
284       {
285         return getJarEntry().getTime();
286       }
287     catch (IOException e)
288       {
289         return -1;
290       }
291   }
292 }