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; 2809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilsonimport java.net.JarURLConnection; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.MalformedURLException; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AccessController; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.Permission; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivilegedAction; 343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.HashMap; 353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Iterator; 363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Map; 373819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport java.util.Set; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarEntry; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarFile; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipFile; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Msg; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Util; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 4609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * This subclass extends {@code URLConnection}. 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class is responsible for connecting and retrieving resources from a Jar 5009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * file which can be anywhere that can be referred to by an URL. 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 5209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilsonpublic class JarURLConnectionImpl extends JarURLConnection { 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 543819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>(); 553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 563819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private URL jarFileURL; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 583819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private InputStream jarInput; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private JarFile jarFile; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private JarEntry jarEntry; 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 643819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson private boolean closed; 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 7109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * @throws IOException 7209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * if there is a problem opening the connection. 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 7409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson public JarURLConnectionImpl(URL url) throws MalformedURLException, 7509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson IOException { 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(url); 773819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURL = getJarFileURL(); 783819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection = jarFileURL.openConnection(); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see java.net.URLConnection#connect() 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void connect() throws IOException { 863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (!connected) { 873819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson findJarFile(); // ensure the file can be found 883819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson findJarEntry(); // ensure the entry, if any, can be found 893819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connected = true; 903819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 9409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Returns the Jar file referred by this {@code URLConnection}. 9509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the JAR file referenced by this connection 973819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thrown if an IO error occurs while connecting to the 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resource. 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public JarFile getJarFile() throws IOException { 1043819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarFile; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 10909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Returns the Jar file referred by this {@code URLConnection} 11009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while connecting to the resource. 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void findJarFile() throws IOException { 1153819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile jar = null; 1163819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (getUseCaches()) { 11709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson synchronized (jarCache) { 1183819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jarCache.get(jarFileURL); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1203819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFile == null) { 1213819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar = openJarFile(); 12209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson synchronized (jarCache) { 1233819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jarCache.get(jarFileURL); 12409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson if (jarFile == null) { 1253819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarCache.put(jarFileURL, jar); 1263819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = jar; 12709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } else { 1283819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar.close(); 1293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 1303819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 13209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } else { 1333819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFile = openJarFile(); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarFile == null) { 1373819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson throw new IOException(); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1393819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 14109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson @SuppressWarnings("nls") 1423819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile openJarFile() throws IOException { 1433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson JarFile jar = null; 14409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson if (jarFileURL.getProtocol().equals("file")) { 14501021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false, 14601021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson "UTF-8")), true, ZipFile.OPEN_READ); 14701021fcb0c9026e81ac2c262caf5e2ec830a7025Jesse Wilson } else { 1483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson final InputStream is = jarFileURL.openConnection().getInputStream(); 1493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson try { 1503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jar = AccessController 15109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson .doPrivileged(new PrivilegedAction<JarFile>() { 15209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson public JarFile run() { 15309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson try { 15409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson File tempJar = File.createTempFile( 15509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson "hyjar_", ".tmp", null); 15609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson tempJar.deleteOnExit(); 15709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson FileOutputStream fos = new FileOutputStream( 15809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson tempJar); 15909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson byte[] buf = new byte[4096]; 16009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson int nbytes = 0; 16109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson while ((nbytes = is.read(buf)) > -1) { 16209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson fos.write(buf, 0, nbytes); 16309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } 16409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson fos.close(); 16509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson return new JarFile(tempJar, true, 16609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson ZipFile.OPEN_READ 16709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson | ZipFile.OPEN_DELETE); 16809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } catch (IOException e) { 16909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson return null; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 17209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson }); 1733819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } finally { 17409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson if (is != null) { 17509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson is.close(); 17609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jar; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 18409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Returns the JarEntry of the entry referenced by this {@code 18509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * URLConnection}. 18609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 18709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * @return the JarEntry referenced 18809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while getting the entry 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public JarEntry getJarEntry() throws IOException { 1943819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarEntry; 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 20009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Look up the JarEntry of the entry referenced by this {@code 20109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * URLConnection}. 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void findJarEntry() throws IOException { 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (getEntryName() == null) { 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarEntry = jarFile.getJarEntry(getEntryName()); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new FileNotFoundException(getEntryName()); 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Creates an input stream for reading from this URL Connection. 2153819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the input stream 2173819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if an IO error occurs while connecting to the resource. 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public InputStream getInputStream() throws IOException { 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (closed) { 22409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson // KA027=Inputstream of the JarURLConnection has been closed 22509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson throw new IllegalStateException(Msg.getString("KA027")); //$NON-NLS-1$ 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 2273819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarInput != null) { 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarInput; 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 23209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson // K00fc=Jar entry not specified 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$ 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarInput = new JarURLConnectionInputStream(jarFile 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .getInputStream(jarEntry), jarFile); 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 24009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Returns the content type of the resource. For jar file itself 24109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * "x-java/jar" should be returned, for jar entries the content type of the 24209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * entry should be returned. Returns non-null results ("content/unknown" for 24309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * unknown types). 24409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the content type 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getContentType() { 2493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (url.getFile().endsWith("!/")) { //$NON-NLS-1$ 2503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // the type for jar file itself is always "x-java/jar" 2513819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return "x-java/jar"; //$NON-NLS-1$ 25209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } 25309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson String cType = null; 25409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson String entryName = getEntryName(); 2553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 25609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson if (entryName != null) { 25709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson // if there is an Jar Entry, get the content type from the name 25809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson cType = guessContentTypeFromName(entryName); 25909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } else { 26009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson try { 26109133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson connect(); 26209133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson cType = jarFileURLConnection.getContentType(); 26309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } catch (IOException ioe) { 26409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson // Ignore 2653819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 26709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson if (cType == null) { 26809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson cType = "content/unknown"; //$NON-NLS-1$ 26909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } 27009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson return cType; 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the content length of the resource. Test cases reveal that if the 27509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * URL is referring to a Jar file, this method answers a content-length 2763819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * returned by URLConnection. For jar entry it should return it's size. 2773819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * Otherwise, it will return -1. 2783819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the content length 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getContentLength() { 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 2843819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 2853819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (jarEntry == null) { 2863819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getContentLength(); 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 28809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson return (int) getJarEntry().getSize(); 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (IOException e) { 29009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson // Ignored 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 29609133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * Returns the object pointed by this {@code URL}. If this URLConnection is 29709133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * pointing to a Jar File (no Jar Entry), this method will return a {@code 29809133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * JarFile} If there is a Jar Entry, it will return the object corresponding 29909133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * to the Jar entry content type. 30009133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return a non-null object 3023819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 30409133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * if an IO error occurred 30509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson * 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ContentHandler 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ContentHandlerFactory 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see java.io.IOException 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see #setContentHandlerFactory(ContentHandlerFactory) 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Object getContent() throws IOException { 3133819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson connect(); 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // if there is no Jar Entry, return a JarFile 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (jarEntry == null) { 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return jarFile; 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return super.getContent(); 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the permission, in this case the subclass, FilePermission object 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which represents the permission necessary for this URLConnection to 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * establish the connection. 3253819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the permission required for this URLConnection. 3273819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IOException 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thrown when an IO exception occurs while creating the 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * permission. 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 3323819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Permission getPermission() throws IOException { 3353819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getPermission(); 3363819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3373819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3393819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public boolean getUseCaches() { 3403819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getUseCaches(); 3413819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3423819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3433819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3443819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public void setUseCaches(boolean usecaches) { 3453819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection.setUseCaches(usecaches); 3463819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3473819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3483819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3493819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public boolean getDefaultUseCaches() { 3503819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson return jarFileURLConnection.getDefaultUseCaches(); 3513819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson 3533819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson @Override 3543819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson public void setDefaultUseCaches(boolean defaultusecaches) { 3553819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson jarFileURLConnection.setDefaultUseCaches(defaultusecaches); 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Closes the cached files. 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static void closeCachedFiles() { 3623819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet(); 36309133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson synchronized (jarCache) { 3643819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson Iterator<Map.Entry<URL, JarFile>> i = s.iterator(); 36509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson while (i.hasNext()) { 3663819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson try { 3673819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson ZipFile zip = i.next().getValue(); 3683819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (zip != null) { 3693819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson zip.close(); 3703819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } 3713819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson } catch (IOException e) { 3723819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson // Ignored 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 37509133811f94298bf72a3bf6ee605f60e7b1b2c81Jesse Wilson } 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private class JarURLConnectionInputStream extends FilterInputStream { 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project InputStream inputStream; 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JarFile jarFile; 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected JarURLConnectionInputStream(InputStream in, JarFile file) { 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(in); 385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project inputStream = in; 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarFile = file; 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void close() throws IOException { 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super.close(); 3923819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson if (!getUseCaches()) { 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project closed = true; 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project jarFile.close(); 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int read() throws IOException { 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.read(); 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int read(byte[] buf, int off, int nbytes) throws IOException { 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.read(buf, off, nbytes); 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public long skip(long nbytes) throws IOException { 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return inputStream.skip(nbytes); 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 414