/* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 in the LICENSE file that * accompanied this code). * * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.net.www.protocol.jar; import java.io.InputStream; import java.io.IOException; import java.io.FileNotFoundException; import java.io.BufferedInputStream; import java.net.URL; import java.net.URLConnection; import java.net.MalformedURLException; import java.net.UnknownServiceException; import java.util.Enumeration; import java.util.Map; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.security.Permission; /** * @author Benjamin Renaud * @since 1.2 */ public class JarURLConnection extends java.net.JarURLConnection { private static final boolean debug = false; /* the Jar file factory. It handles both retrieval and caching. */ private static final JarFileFactory factory = JarFileFactory.getInstance(); /* the url for the Jar file */ private URL jarFileURL; /* the permission to get this JAR file. This is the actual, ultimate, * permission, returned by the jar file factory. */ private Permission permission; /* the url connection for the JAR file */ private URLConnection jarFileURLConnection; /* the entry name, if any */ private String entryName; /* the JarEntry */ private JarEntry jarEntry; /* the jar file corresponding to this connection */ private JarFile jarFile; /* the content type for this connection */ private String contentType; public JarURLConnection(URL url, Handler handler) throws MalformedURLException, IOException { super(url); jarFileURL = getJarFileURL(); jarFileURLConnection = jarFileURL.openConnection(); entryName = getEntryName(); } public JarFile getJarFile() throws IOException { connect(); return jarFile; } public JarEntry getJarEntry() throws IOException { connect(); return jarEntry; } public Permission getPermission() throws IOException { return jarFileURLConnection.getPermission(); } class JarURLInputStream extends java.io.FilterInputStream { JarURLInputStream (InputStream src) { super (src); } public void close () throws IOException { try { super.close(); } finally { if (!getUseCaches()) { jarFile.close(); } } } } public void connect() throws IOException { if (!connected) { /* the factory call will do the security checks */ jarFile = factory.get(getJarFileURL(), getUseCaches()); /* we also ask the factory the permission that was required * to get the jarFile, and set it as our permission. */ if (getUseCaches()) { jarFileURLConnection = factory.getConnection(jarFile); } if ((entryName != null)) { jarEntry = (JarEntry)jarFile.getEntry(entryName); if (jarEntry == null) { try { if (!getUseCaches()) { jarFile.close(); } } catch (Exception e) { } throw new FileNotFoundException("JAR entry " + entryName + " not found in " + jarFile.getName()); } } connected = true; } } public InputStream getInputStream() throws IOException { connect(); InputStream result = null; if (entryName == null) { throw new IOException("no entry name specified"); } else { if (jarEntry == null) { throw new FileNotFoundException("JAR entry " + entryName + " not found in " + jarFile.getName()); } result = new JarURLInputStream (jarFile.getInputStream(jarEntry)); } return result; } public int getContentLength() { long result = getContentLengthLong(); if (result > Integer.MAX_VALUE) return -1; return (int) result; } public long getContentLengthLong() { long result = -1; try { connect(); if (jarEntry == null) { /* if the URL referes to an archive */ result = jarFileURLConnection.getContentLengthLong(); } else { /* if the URL referes to an archive entry */ result = getJarEntry().getSize(); } } catch (IOException e) { } return result; } public Object getContent() throws IOException { Object result = null; connect(); if (entryName == null) { result = jarFile; } else { result = super.getContent(); } return result; } public String getContentType() { if (contentType == null) { if (entryName == null) { contentType = "x-java/jar"; } else { try { connect(); InputStream in = jarFile.getInputStream(jarEntry); contentType = guessContentTypeFromStream( new BufferedInputStream(in)); in.close(); } catch (IOException e) { // don't do anything } } if (contentType == null) { contentType = guessContentTypeFromName(entryName); } if (contentType == null) { contentType = "content/unknown"; } } return contentType; } public String getHeaderField(String name) { return jarFileURLConnection.getHeaderField(name); } /** * Sets the general request property. * * @param key the keyword by which the request is known * (e.g., "accept"). * @param value the value associated with it. */ public void setRequestProperty(String key, String value) { jarFileURLConnection.setRequestProperty(key, value); } /** * Returns the value of the named general request property for this * connection. * * @return the value of the named general request property for this * connection. */ public String getRequestProperty(String key) { return jarFileURLConnection.getRequestProperty(key); } /** * Adds a general request property specified by a * key-value pair. This method will not overwrite * existing values associated with the same key. * * @param key the keyword by which the request is known * (e.g., "accept"). * @param value the value associated with it. */ public void addRequestProperty(String key, String value) { jarFileURLConnection.addRequestProperty(key, value); } /** * Returns an unmodifiable Map of general request * properties for this connection. The Map keys * are Strings that represent the request-header * field names. Each Map value is a unmodifiable List * of Strings that represents the corresponding * field values. * * @return a Map of the general request properties for this connection. */ public Map> getRequestProperties() { return jarFileURLConnection.getRequestProperties(); } /** * Set the value of the allowUserInteraction field of * this URLConnection. * * @param allowuserinteraction the new value. * @see java.net.URLConnection#allowUserInteraction */ public void setAllowUserInteraction(boolean allowuserinteraction) { jarFileURLConnection.setAllowUserInteraction(allowuserinteraction); } /** * Returns the value of the allowUserInteraction field for * this object. * * @return the value of the allowUserInteraction field for * this object. * @see java.net.URLConnection#allowUserInteraction */ public boolean getAllowUserInteraction() { return jarFileURLConnection.getAllowUserInteraction(); } /* * cache control */ /** * Sets the value of the useCaches field of this * URLConnection to the specified value. *

* Some protocols do caching of documents. Occasionally, it is important * to be able to "tunnel through" and ignore the caches (e.g., the * "reload" button in a browser). If the UseCaches flag on a connection * is true, the connection is allowed to use whatever caches it can. * If false, caches are to be ignored. * The default value comes from DefaultUseCaches, which defaults to * true. * * @see java.net.URLConnection#useCaches */ public void setUseCaches(boolean usecaches) { jarFileURLConnection.setUseCaches(usecaches); } /** * Returns the value of this URLConnection's * useCaches field. * * @return the value of this URLConnection's * useCaches field. * @see java.net.URLConnection#useCaches */ public boolean getUseCaches() { return jarFileURLConnection.getUseCaches(); } /** * Sets the value of the ifModifiedSince field of * this URLConnection to the specified value. * * @param ifmodifiedsince the new value. * @see java.net.URLConnection#ifModifiedSince */ public void setIfModifiedSince(long ifmodifiedsince) { jarFileURLConnection.setIfModifiedSince(ifmodifiedsince); } /** * Sets the default value of the useCaches field to the * specified value. * * @param defaultusecaches the new value. * @see java.net.URLConnection#useCaches */ public void setDefaultUseCaches(boolean defaultusecaches) { jarFileURLConnection.setDefaultUseCaches(defaultusecaches); } /** * Returns the default value of a URLConnection's * useCaches flag. *

* Ths default is "sticky", being a part of the static state of all * URLConnections. This flag applies to the next, and all following * URLConnections that are created. * * @return the default value of a URLConnection's * useCaches flag. * @see java.net.URLConnection#useCaches */ public boolean getDefaultUseCaches() { return jarFileURLConnection.getDefaultUseCaches(); } }