OSDN Git Service

070b3375d19cc64276921c76743bfdfebe6f15a9
[pf3gnuchains/gcc-fork.git] / libjava / java / util / jar / JarFile.java
1 /* JarFile.java - Representation of a jar file
2    Copyright (C) 2000, 2003, 2004 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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 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 package java.util.jar;
39
40 import java.io.File;
41 import java.io.FileNotFoundException;
42 import java.io.IOException;
43 import java.io.InputStream;
44 import java.util.Enumeration;
45 import java.util.zip.ZipEntry;
46 import java.util.zip.ZipException;
47 import java.util.zip.ZipFile;
48
49 /**
50  * Representation of a jar file.
51  * <p>
52  * Note that this class is not a subclass of java.io.File but a subclass of
53  * java.util.zip.ZipFile and you can only read JarFiles with it (although
54  * there are constructors that take a File object).
55  * <p>
56  * XXX - verification of Manifest signatures is not yet implemented.
57  *
58  * @since 1.2
59  * @author Mark Wielaard (mark@klomp.org)
60  */
61 public class JarFile extends ZipFile
62 {
63   // Fields
64
65   /** The name of the manifest entry: META-INF/MANIFEST.MF */
66   public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
67
68   /**
69    * The manifest of this file, if any, otherwise null.
70    * Read when first needed.
71    */
72   private Manifest manifest;
73
74   /** Whether to verify the manifest and all entries. */
75   private boolean verify;
76
77   /** Whether the has already been loaded. */
78   private boolean manifestRead = false;
79
80   // Constructors
81
82   /**
83    * Creates a new JarFile. All jar entries are verified (when a Manifest file
84    * for this JarFile exists). You need to actually open and read the complete
85    * jar entry (with <code>getInputStream()</code>) to check its signature.
86    *
87    * @param fileName the name of the file to open
88    * @exception FileNotFoundException if the fileName cannot be found
89    * @exception IOException if another IO exception occurs while reading
90    */
91   public JarFile(String fileName) throws FileNotFoundException, IOException
92   {
93     this(fileName, true);
94   }
95
96   /**
97    * Creates a new JarFile. If verify is true then all jar entries are
98    * verified (when a Manifest file for this JarFile exists). You need to
99    * actually open and read the complete jar entry
100    * (with <code>getInputStream()</code>) to check its signature.
101    *
102    * @param fileName the name of the file to open
103    * @param verify checks manifest and entries when true and a manifest
104    * exists, when false no checks are made
105    * @exception FileNotFoundException if the fileName cannot be found
106    * @exception IOException if another IO exception occurs while reading
107    */
108   public JarFile(String fileName, boolean verify) throws
109     FileNotFoundException, IOException
110   {
111     super(fileName);
112     if (verify)
113       {
114         manifest = readManifest();
115         verify();
116       }
117   }
118
119   /**
120    * Creates a new JarFile. All jar entries are verified (when a Manifest file
121    * for this JarFile exists). You need to actually open and read the complete
122    * jar entry (with <code>getInputStream()</code>) to check its signature.
123    *
124    * @param file the file to open as a jar file
125    * @exception FileNotFoundException if the file does not exits
126    * @exception IOException if another IO exception occurs while reading
127    */
128   public JarFile(File file) throws FileNotFoundException, IOException
129   {
130     this(file, true);
131   }
132
133   /**
134    * Creates a new JarFile. If verify is true then all jar entries are
135    * verified (when a Manifest file for this JarFile exists). You need to
136    * actually open and read the complete jar entry
137    * (with <code>getInputStream()</code>) to check its signature.
138    *
139    * @param file the file to open to open as a jar file
140    * @param verify checks manifest and entries when true and a manifest
141    * exists, when false no checks are made
142    * @exception FileNotFoundException if file does not exist
143    * @exception IOException if another IO exception occurs while reading
144    */
145   public JarFile(File file, boolean verify) throws FileNotFoundException,
146     IOException
147   {
148     super(file);
149     if (verify)
150       {
151         manifest = readManifest();
152         verify();
153       }
154   }
155
156   /**
157    * Creates a new JarFile with the indicated mode. If verify is true then
158    * all jar entries are verified (when a Manifest file for this JarFile
159    * exists). You need to actually open and read the complete jar entry
160    * (with <code>getInputStream()</code>) to check its signature.
161    * manifest and if the manifest exists and verify is true verfies it.
162    *
163    * @param file the file to open to open as a jar file
164    * @param verify checks manifest and entries when true and a manifest
165    * exists, when false no checks are made
166    * @param mode either ZipFile.OPEN_READ or
167    *             (ZipFile.OPEN_READ | ZipFile.OPEN_DELETE)
168    * @exception FileNotFoundException if the file does not exist
169    * @exception IOException if another IO exception occurs while reading
170    * @exception IllegalArgumentException when given an illegal mode
171    * 
172    * @since 1.3
173    */
174   public JarFile(File file, boolean verify, int mode) throws
175     FileNotFoundException, IOException, IllegalArgumentException
176   {
177     super(file, mode);
178     if (verify)
179       {
180         manifest = readManifest();
181         verify();
182       }
183   }
184
185   // Methods
186
187   /**
188    * XXX - should verify the manifest file
189    */
190   private void verify()
191   {
192     // only check if manifest is not null
193     if (manifest == null)
194       {
195         verify = false;
196         return;
197       }
198
199     verify = true;
200     // XXX - verify manifest
201   }
202
203   /**
204    * Parses and returns the manifest if it exists, otherwise returns null.
205    */
206   private Manifest readManifest()
207   {
208     try
209       {
210         ZipEntry manEntry = super.getEntry(MANIFEST_NAME);
211         if (manEntry != null)
212           {
213             InputStream in = super.getInputStream(manEntry);
214             manifestRead = true;
215             return new Manifest(in);
216           }
217         else
218           {
219             manifestRead = true;
220             return null;
221           }
222       }
223     catch (IOException ioe)
224       {
225         manifestRead = true;
226         return null;
227       }
228   }
229
230   /**
231    * Returns a enumeration of all the entries in the JarFile.
232    * Note that also the Jar META-INF entries are returned.
233    *
234    * @exception IllegalStateException when the JarFile is already closed
235    */
236   public Enumeration entries() throws IllegalStateException
237   {
238     return new JarEnumeration(super.entries());
239   }
240
241   /**
242    * Wraps a given Zip Entries Enumeration. For every zip entry a
243    * JarEntry is created and the corresponding Attributes are looked up.
244    * XXX - Should also look up the certificates.
245    */
246   private class JarEnumeration implements Enumeration
247   {
248
249     private final Enumeration entries;
250
251     JarEnumeration(Enumeration e)
252     {
253       entries = e;
254     }
255
256     public boolean hasMoreElements()
257     {
258       return entries.hasMoreElements();
259     }
260
261     public Object nextElement()
262     {
263       ZipEntry zip = (ZipEntry) entries.nextElement();
264       JarEntry jar = new JarEntry(zip);
265       Manifest manifest;
266       try
267         {
268           manifest = getManifest();
269         }
270       catch (IOException ioe)
271         {
272           manifest = null;
273         }
274
275       if (manifest != null)
276         {
277           jar.attr = manifest.getAttributes(jar.getName());
278         }
279       // XXX jar.certs
280       return jar;
281     }
282   }
283
284   /**
285    * XXX
286    * It actually returns a JarEntry not a zipEntry
287    * @param name XXX
288    */
289   public ZipEntry getEntry(String name)
290   {
291     ZipEntry entry = super.getEntry(name);
292     if (entry != null)
293       {
294         JarEntry jarEntry = new JarEntry(entry);
295         Manifest manifest;
296         try
297           {
298             manifest = getManifest();
299           }
300         catch (IOException ioe)
301           {
302             manifest = null;
303           }
304
305         if (manifest != null)
306           {
307             jarEntry.attr = manifest.getAttributes(name);
308             // XXX jarEntry.certs
309           }
310         return jarEntry;
311       }
312     return null;
313   }
314
315   /**
316    * XXX should verify the inputstream
317    * @param entry XXX
318    * @exception ZipException XXX
319    * @exception IOException XXX
320    */
321   public synchronized InputStream getInputStream(ZipEntry entry) throws
322     ZipException, IOException
323   {
324     return super.getInputStream(entry); // XXX verify
325   }
326
327   /**
328    * Returns the JarEntry that belongs to the name if such an entry
329    * exists in the JarFile. Returns null otherwise
330    * Convenience method that just casts the result from <code>getEntry</code>
331    * to a JarEntry.
332    *
333    * @param name the jar entry name to look up
334    * @return the JarEntry if it exists, null otherwise
335    */
336   public JarEntry getJarEntry(String name)
337   {
338     return (JarEntry) getEntry(name);
339   }
340
341   /**
342    * Returns the manifest for this JarFile or null when the JarFile does not
343    * contain a manifest file.
344    */
345   public Manifest getManifest() throws IOException
346   {
347     if (!manifestRead)
348       manifest = readManifest();
349
350     return manifest;
351   }
352 }