/* * @(#)URLJarFile.java 1.7 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package sun.net.www.protocol.jar; import java.io.*; import java.net.*; import java.util.*; import java.util.jar.*; import java.util.zip.ZipFile; import java.util.zip.ZipEntry; import java.security.cert.Certificate; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import sun.net.www.ParseUtil; /* URL jar file is a common JarFile subtype used for JarURLConnection */ class URLJarFile extends JarFile { private static int BUF_SIZE = 2048; private Manifest superMan; private Attributes superAttr; private Map superEntries; static JarFile getJarFile(URL url) throws IOException { if (isFileURL(url)) return new URLJarFile(url); else { return retrieve(url); } } private URLJarFile(File file) throws IOException { super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE); } private URLJarFile(URL url) throws IOException { super(ParseUtil.decode(url.getFile())); } private static boolean isFileURL(URL url) { return url.getProtocol().equalsIgnoreCase("file"); } /* * close the jar file. */ protected void finalize() throws IOException { close(); } /** * Returns the <code>ZipEntry</code> for the given entry name or * <code>null</code> if not found. * * @param name the JAR file entry name * @return the <code>ZipEntry</code> for the given entry name or * <code>null</code> if not found * @see java.util.zip.ZipEntry */ public ZipEntry getEntry(String name) { ZipEntry ze = super.getEntry(name); if (ze != null) { if (ze instanceof JarEntry) return new URLJarFileEntry((JarEntry)ze); else throw new InternalError(super.getClass() + " returned unexpected entry type " + ze.getClass()); } return null; } public Manifest getManifest() throws IOException { if (!isSuperMan()) { return null; } Manifest man = new Manifest(); Attributes attr = man.getMainAttributes(); attr.putAll((Map)superAttr.clone()); // now deep copy the manifest entries if (superEntries != null) { Map entries = man.getEntries(); Iterator it = superEntries.keySet().iterator(); while (it.hasNext()) { Object key = it.next(); Attributes at = (Attributes)superEntries.get(key); entries.put(key, at.clone()); } } return man; } // optimal side-effects private synchronized boolean isSuperMan() throws IOException { if (superMan == null) { superMan = super.getManifest(); } if (superMan != null) { superAttr = superMan.getMainAttributes(); superEntries = superMan.getEntries(); return true; } else return false; } /** * Given a URL, retrieves a JAR file, caches it to disk, and creates a * cached JAR file object. */ private static JarFile retrieve(final URL url) throws IOException { JarFile result = null; /* get the stream before asserting privileges */ final InputStream in = url.openConnection().getInputStream(); try { result = (JarFile) AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws IOException { OutputStream out = null; try { File tmpFile = File.createTempFile("jar_cache", null); tmpFile.deleteOnExit(); out = new FileOutputStream(tmpFile); int read = 0; byte[] buf = new byte[BUF_SIZE]; while ((read = in.read(buf)) != -1) { out.write(buf, 0, read); } out.close(); out = null; return new URLJarFile(tmpFile); } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } }); } catch (PrivilegedActionException pae) { throw (IOException) pae.getException(); } return result; } private class URLJarFileEntry extends JarEntry { private JarEntry je; URLJarFileEntry(JarEntry je) { super(je); this.je=je; } public Attributes getAttributes() throws IOException { if (URLJarFile.this.isSuperMan()) { Map e = URLJarFile.this.superEntries; if (e != null) { Attributes a = (Attributes)e.get(getName()); if (a != null) return (Attributes)a.clone(); } } return null; } public java.security.cert.Certificate[] getCertificates() { Certificate[] certs = je.getCertificates(); return certs == null? null: (Certificate[])certs.clone(); } } }