JarURLConnectionImpl.java revision 3819a76e7c1f49253f0e077bd497f149340c02b8
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership. 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License. You may obtain a copy of the License at 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.luni.internal.net.www.protocol.jar; 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.File; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FileNotFoundException; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FileOutputStream; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FilterInputStream; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.ContentHandler; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.ContentHandlerFactory; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.MalformedURLException; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AccessController; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.Permission; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivilegedAction; 333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.HashMap; 343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Iterator; 353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Map; 363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Set; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarEntry; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarFile; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipFile; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Msg; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Util; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This subclass extends <code>URLConnection</code>. 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 473819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class is responsible for connecting and retrieving resources from a Jar 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file which can be anywhere that can be refered to by an URL. 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class JarURLConnection extends java.net.JarURLConnection { 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 533819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>(); 543819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private URL jarFileURL; 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 573819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private InputStream jarInput; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private JarFile jarFile; 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private JarEntry jarEntry; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 633819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private boolean closed; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param url 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the URL of the JAR 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws MalformedURLException 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if the URL is malformed 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 723819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException { 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(url); 743819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURL = getJarFileURL(); 753819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection = jarFileURL.openConnection(); 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see java.net.URLConnection#connect() 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void connect() throws IOException { 833819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (!connected) { 843819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson findJarFile(); // ensure the file can be found 853819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson findJarEntry(); // ensure the entry, if any, can be found 863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connected = true; 873819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the Jar file refered by this <code>URLConnection</code> 923819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the JAR file referenced by this connection 943819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thrown if an IO error occurs while connecting to the 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resource. 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public JarFile getJarFile() throws IOException { 1013819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarFile; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the Jar file refered by this <code>URLConnection</code> 1073819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while connecting to the resource. 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void findJarFile() throws IOException { 1123819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile jar = null; 1133819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (getUseCaches()) { 1143819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson synchronized(jarCache){ 1153819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jarCache.get(jarFileURL); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1173819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFile == null) { 1183819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar = openJarFile(); 1193819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson synchronized(jarCache){ 1203819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jarCache.get(jarFileURL); 1213819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFile == null){ 1223819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarCache.put(jarFileURL, jar); 1233819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jar; 1243819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson }else{ 1253819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar.close(); 1263819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 1273819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson }else{ 1303819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = openJarFile(); 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFile == null) { 1343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson throw new IOException(); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile openJarFile() throws IOException { 1393819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile jar = null; 1403819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$ 1413819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false)), 1423819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson true, ZipFile.OPEN_READ); 1433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } else{ 1443819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson final InputStream is = jarFileURL.openConnection().getInputStream(); 1453819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson try { 1463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar = AccessController 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .doPrivileged(new PrivilegedAction<JarFile>() { 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public JarFile run() { 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$ 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ".tmp", null); //$NON-NLS-1$ 1523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson tempJar.deleteOnExit(); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project FileOutputStream fos = new FileOutputStream( 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project tempJar); 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] buf = new byte[4096]; 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int nbytes = 0; 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while ((nbytes = is.read(buf)) > -1) { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fos.write(buf, 0, nbytes); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fos.close(); 1613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return new JarFile(tempJar, 1623819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE); 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IOException e) { 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }); 1683819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } finally { 1693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (is != null) is.close(); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jar; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the JarEntry of the entry referenced by this 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <code>URLConnection</code>. 1793819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return java.util.jar.JarEntry the JarEntry referenced 1813819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while getting the entry 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public JarEntry getJarEntry() throws IOException { 1873819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarEntry; 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Look up the JarEntry of the entry referenced by this 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <code>URLConnection</code>. 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void findJarEntry() throws IOException { 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (getEntryName() == null) { 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarEntry = jarFile.getJarEntry(getEntryName()); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new FileNotFoundException(getEntryName()); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Creates an input stream for reading from this URL Connection. 2083819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the input stream 2103819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while connecting to the resource. 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public InputStream getInputStream() throws IOException { 2163819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (closed) { 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalStateException(Msg.getString("KA027")); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 2203819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarInput != null) { 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarInput; 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$ 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarInput = new JarURLConnectionInputStream(jarFile 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .getInputStream(jarEntry), jarFile); 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 2323819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * Returns the content type of the resource. 2333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * For jar file itself "x-java/jar" should be returned, 2343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * for jar entries the content type of the entry should be returned. 2353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * Returns non-null results ("content/unknown" for unknown types). 2363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the content type 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getContentType() { 2413819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ 2423819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // the type for jar file itself is always "x-java/jar" 2433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return "x-java/jar"; //$NON-NLS-1$ 2443819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } else { 2453819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson String cType = null; 2463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson String entryName = getEntryName(); 2473819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 2483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (entryName != null) { 2493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // if there is an Jar Entry, get the content type from the name 2503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson cType = guessContentTypeFromName(entryName); 2513819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } else { 2523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson try { 2533819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 2543819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson cType = jarFileURLConnection.getContentType(); 2553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } catch (IOException ioe) { 2563819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // Ignore 2573819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 2593819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (cType == null) { 2603819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson cType = "content/unknown"; //$NON-NLS-1$ 2613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 2623819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return cType; 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the content length of the resource. Test cases reveal that if the 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * URL is refering to a Jar file, this method returns a content-length 2693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * returned by URLConnection. For jar entry it should return it's size. 2703819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * Otherwise, it will return -1. 2713819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the content length 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getContentLength() { 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 2773819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 2783819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarEntry == null) { 2793819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getContentLength(); 2803819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } else { 2813819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return (int) getJarEntry().getSize(); 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IOException e) { 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //Ignored 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the object pointed by this <code>URL</code>. If this 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * URLConnection is pointing to a Jar File (no Jar Entry), this method will 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return a <code>JarFile</code> If there is a Jar Entry, it will return 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the object corresponding to the Jar entry content type. 2943819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return a non-null object 2963819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occured 2993819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ContentHandler 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ContentHandlerFactory 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see java.io.IOException 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see #setContentHandlerFactory(ContentHandlerFactory) 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Object getContent() throws IOException { 3073819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // if there is no Jar Entry, return a JarFile 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarFile; 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return super.getContent(); 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the permission, in this case the subclass, FilePermission object 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which represents the permission necessary for this URLConnection to 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * establish the connection. 3193819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the permission required for this URLConnection. 3213819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thrown when an IO exception occurs while creating the 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * permission. 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3263819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Permission getPermission() throws IOException { 3293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getPermission(); 3303819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3313819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3323819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public boolean getUseCaches() { 3343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getUseCaches(); 3353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3373819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public void setUseCaches(boolean usecaches) { 3393819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection.setUseCaches(usecaches); 3403819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3413819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3423819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public boolean getDefaultUseCaches() { 3443819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getDefaultUseCaches(); 3453819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3473819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public void setDefaultUseCaches(boolean defaultusecaches) { 3493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection.setDefaultUseCaches(defaultusecaches); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Closes the cached files. 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static void closeCachedFiles() { 3563819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet(); 3573819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson synchronized(jarCache){ 3583819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson Iterator<Map.Entry<URL, JarFile>> i = s.iterator(); 3593819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson while(i.hasNext()){ 3603819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson try { 3613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson ZipFile zip = i.next().getValue(); 3623819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (zip != null) { 3633819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson zip.close(); 3643819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3653819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } catch (IOException e) { 3663819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // Ignored 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 3693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private class JarURLConnectionInputStream extends FilterInputStream { 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project InputStream inputStream; 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JarFile jarFile; 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected JarURLConnectionInputStream(InputStream in, JarFile file) { 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(in); 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project inputStream = in; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarFile = file; 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void close() throws IOException { 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super.close(); 3863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (!getUseCaches()) { 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project closed = true; 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarFile.close(); 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int read() throws IOException { 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.read(); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int read(byte[] buf, int off, int nbytes) throws IOException { 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.read(buf, off, nbytes); 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public long skip(long nbytes) throws IOException { 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.skip(nbytes); 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 408