JarURLConnectionImpl.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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.lang.ref.ReferenceQueue;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.lang.ref.WeakReference;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.ContentHandler;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.ContentHandlerFactory;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.MalformedURLException;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AccessController;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.Permission;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivilegedAction;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Comparator;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Date;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Enumeration;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Hashtable;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.TreeSet;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarEntry;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.jar.JarFile;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipFile;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// BEGIN android-removed
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// import org.apache.harmony.kernel.vm.VM;
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// END android-removed
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Msg;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.util.Util;
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This subclass extends <code>URLConnection</code>.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class is responsible for connecting and retrieving resources from a Jar
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * file which can be anywhere that can be refered to by an URL.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class JarURLConnection extends java.net.JarURLConnection {
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static Hashtable<String, CacheEntry<? extends JarFile>> jarCache = new Hashtable<String, CacheEntry<?>>();
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    InputStream jarInput;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private JarFile jarFile;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private JarEntry jarEntry;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean closed;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ReferenceQueue<JarFile> cacheQueue = new ReferenceQueue<JarFile>();
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static TreeSet<LRUKey> lru = new TreeSet<LRUKey>(
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new LRUComparator<LRUKey>());
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static int Limit;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Limit = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public Integer run() {
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return Integer.getInteger("jar.cacheSize", 500); //$NON-NLS-1$
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        });
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-removed
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // TODO this needs to be implemented once this is available.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // VM.closeJars();
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-removed
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final class CacheEntry<T extends JarFile> extends WeakReference<T> {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object key;
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CacheEntry(T jar, String key, ReferenceQueue<JarFile> queue) {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super(jar, queue);
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.key = key;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final class LRUKey {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JarFile jar;
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long ts;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LRUKey(JarFile file, long time) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            jar = file;
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ts = time;
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @see java.lang.Object#equals(java.lang.Object)
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean equals(Object obj) {
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return (obj instanceof LRUKey) &&
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                (jar == ((LRUKey) obj).jar);
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int hashCode() {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return jar.hashCode();
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final class LRUComparator<T> implements Comparator<LRUKey> {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LRUComparator() {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int compare(LRUKey o1, LRUKey o2) {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((o1).ts > (o2).ts) {
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return (o1).ts == (o2).ts ? 0 : -1;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param o1
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *            an object to compare
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param o2
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *            an object to compare
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @return <code>true</code> if the objects are equal,
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *         <code>false</code> otherwise.
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean equals(Object o1, Object o2) {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return o1.equals(o2);
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param url
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the URL of the JAR
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws MalformedURLException
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the URL is malformed
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarURLConnection(java.net.URL url) throws MalformedURLException {
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(url);
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.net.URLConnection#connect()
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void connect() throws IOException {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jarFileURLConnection = getJarFileURL().openConnection();
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        findJarFile(); // ensure the file can be found
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        findJarEntry(); // ensure the entry, if any, can be found
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        connected = true;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the Jar file refered by this <code>URLConnection</code>
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the JAR file referenced by this connection
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             thrown if an IO error occurs while connecting to the
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             resource.
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile getJarFile() throws IOException {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!connected) {
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            connect();
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return jarFile;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the Jar file refered by this <code>URLConnection</code>
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an IO error occurs while connecting to the resource.
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void findJarFile() throws IOException {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        URL jarFileURL = getJarFileURL();
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String fileName = jarFileURL.getFile();
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if(!new File(Util.decode(fileName,false)).exists()){
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // KA026=JAR entry {0} not found in {1}
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new FileNotFoundException(Msg.getString("KA026", //$NON-NLS-1$
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        getEntryName(), fileName));
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String host = jarFileURL.getHost();
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (host != null && host.length() > 0) {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fileName = "//" + host + fileName; //$NON-NLS-1$
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            jarFile = openJarFile(fileName, fileName, false);
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final String externalForm = jarFileURLConnection.getURL()
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .toExternalForm();
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jarFile = AccessController
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .doPrivileged(new PrivilegedAction<JarFile>() {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    public JarFile run() {
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        try {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            return openJarFile(null, externalForm, false);
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } catch (IOException e) {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            return null;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                });
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarFile != null) {
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Build a temp jar file
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final InputStream is = jarFileURLConnection.getInputStream();
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            jarFile = AccessController
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    .doPrivileged(new PrivilegedAction<JarFile>() {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        public JarFile run() {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            try {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        ".tmp", null); //$NON-NLS-1$
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                FileOutputStream fos = new FileOutputStream(
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        tempJar);
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                byte[] buf = new byte[4096];
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                int nbytes = 0;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                while ((nbytes = is.read(buf)) > -1) {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    fos.write(buf, 0, nbytes);
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                }
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                fos.close();
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                String path = tempJar.getPath();
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                return openJarFile(path, externalForm, true);
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            } catch (IOException e) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                return null;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    });
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } finally {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            is.close();
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarFile == null) {
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException();
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarFile openJarFile(String fileString, String key, boolean temp)
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JarFile jar = null;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (useCaches) {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CacheEntry<? extends JarFile> entry;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while ((entry = (CacheEntry<? extends JarFile>) cacheQueue.poll()) != null) {
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                jarCache.remove(entry.key);
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            entry = jarCache.get(key);
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (entry != null) {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                jar = entry.get();
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (jar == null && fileString != null) {
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int flags = ZipFile.OPEN_READ
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + (temp ? ZipFile.OPEN_DELETE : 0);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                jar = new JarFile(new File(Util.decode(fileString, false)),
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        true, flags);
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                jarCache
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        .put(key, new CacheEntry<JarFile>(jar, key, cacheQueue));
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                SecurityManager security = System.getSecurityManager();
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (security != null) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    security.checkPermission(getPermission());
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (temp) {
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    lru.remove(new LRUKey(jar, 0));
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (fileString != null) {
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            jar = new JarFile(new File(Util.decode(fileString, false)), true,
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    flags);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (temp) {
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lru.add(new LRUKey(jar, new Date().getTime()));
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (lru.size() > Limit) {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                lru.remove(lru.first());
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return jar;
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the JarEntry of the entry referenced by this
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>URLConnection</code>.
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return java.util.jar.JarEntry the JarEntry referenced
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an IO error occurs while getting the entry
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarEntry getJarEntry() throws IOException {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!connected) {
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            connect();
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return jarEntry;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Look up the JarEntry of the entry referenced by this
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <code>URLConnection</code>.
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void findJarEntry() throws IOException {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (getEntryName() == null) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        jarEntry = jarFile.getJarEntry(getEntryName());
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarEntry == null) {
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new FileNotFoundException(getEntryName());
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Creates an input stream for reading from this URL Connection.
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the input stream
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an IO error occurs while connecting to the resource.
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public InputStream getInputStream() throws IOException {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (closed) {
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalStateException(Msg.getString("KA027"));
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!connected) {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            connect();
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarInput != null) {
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return jarInput;
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarEntry == null) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return jarInput = new JarURLConnectionInputStream(jarFile
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .getInputStream(jarEntry), jarFile);
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the content type of the resource. Test cases reveal that only if
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the URL is refering to a Jar file, that this method returns a non-null
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * value - x-java/jar.
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the content type
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String getContentType() {
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // it could also return "x-java/jar" which jdk returns but here, we get
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // it from the URLConnection
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return getJarFileURL().openConnection().getContentType();
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IOException ioe) {
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Ignore
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // if there is an Jar Entry, get the content type from the name
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return guessContentTypeFromName(url.getFile());
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the content length of the resource. Test cases reveal that if the
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * URL is refering to a Jar file, this method returns a content-length
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returned by URLConnection. If not, it will return -1.
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the content length
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getContentLength() {
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return getJarFileURL().openConnection().getContentLength();
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IOException e) {
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //Ignored
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the object pointed by this <code>URL</code>. If this
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * URLConnection is pointing to a Jar File (no Jar Entry), this method will
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return a <code>JarFile</code> If there is a Jar Entry, it will return
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object corresponding to the Jar entry content type.
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return a non-null object
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an IO error occured
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see ContentHandler
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see ContentHandlerFactory
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.io.IOException
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #setContentHandlerFactory(ContentHandlerFactory)
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Object getContent() throws IOException {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!connected) {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            connect();
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // if there is no Jar Entry, return a JarFile
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarEntry == null) {
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return jarFile;
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return super.getContent();
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the permission, in this case the subclass, FilePermission object
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which represents the permission necessary for this URLConnection to
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * establish the connection.
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the permission required for this URLConnection.
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             thrown when an IO exception occurs while creating the
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             permission.
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Permission getPermission() throws IOException {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (jarFileURLConnection != null) {
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return jarFileURLConnection.getPermission();
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getJarFileURL().openConnection().getPermission();
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Closes the cached files.
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void closeCachedFiles() {
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Enumeration<CacheEntry<? extends JarFile>> elemEnum = jarCache
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .elements();
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (elemEnum.hasMoreElements()) {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ZipFile zip = elemEnum.nextElement().get();
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (zip != null) {
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    zip.close();
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (IOException e) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Ignored
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private class JarURLConnectionInputStream extends FilterInputStream {
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InputStream inputStream;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JarFile jarFile;
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        protected JarURLConnectionInputStream(InputStream in, JarFile file) {
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super(in);
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            inputStream = in;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            jarFile = file;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void close() throws IOException {
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super.close();
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!useCaches) {
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                closed = true;
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                jarFile.close();
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read() throws IOException {
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return inputStream.read();
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read(byte[] buf, int off, int nbytes) throws IOException {
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return inputStream.read(buf, off, nbytes);
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public long skip(long nbytes) throws IOException {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return inputStream.skip(nbytes);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
503