1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution,
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: InstrClassLoader.java,v 1.1.1.1.2.2 2004/07/16 23:32:03 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.rt;
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File;
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException;
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.InputStream;
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.PrintWriter;
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.MalformedURLException;
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.URL;
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.URLClassLoader;
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.security.CodeSource;
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.security.cert.Certificate;
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Map;
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger;
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.ByteArrayOStream;
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert;
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants;
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.filter.IInclExclFilter;
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class InstrClassLoader extends URLClassLoader
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: proper security [use PrivilegedAction as needed]
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: [see above as well] need to keep track of res URLs to support [path] exclusion patterns
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: improve error handling so it is clear when errors come from buggy instrumentation
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static final String PROPERTY_FORCED_DELEGATION_FILTER  = "clsload.forced_delegation_filter";
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static final String PROPERTY_THROUGH_DELEGATION_FILTER  = "clsload.through_delegation_filter";
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public InstrClassLoader (final ClassLoader parent, final File [] classpath,
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                             final IInclExclFilter forcedDelegationFilter,
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                             final IInclExclFilter throughDelegationFilter,
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                             final IClassLoadHook hook, final Map cache)
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws MalformedURLException
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // setting ClassLoader.parent to null disables the standard delegation
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // behavior in a few places, including URLClassLoader.getResource():
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        super (filesToURLs (classpath), null);
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // TODO: arg validation
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_hook = hook;
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_cache = cache; // can be null
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_forcedDelegationFilter = forcedDelegationFilter;
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_throughDelegationFilter = throughDelegationFilter;
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_parent = parent;
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_bufPool = new PoolEntry [BAOS_POOL_SIZE];
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_log = Logger.getLogger ();
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Overrides java.lang.ClassLoader.loadClass() to change the usual parent-child
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * delegation rules just enough to be able to 'replace' the parent loader. This
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * also has the effect of detecting 'system' classes without doing any class
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * name-based matching.
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public synchronized final Class loadClass (final String name, final boolean resolve)
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws ClassNotFoundException
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final boolean trace1 = m_log.atTRACE1 ();
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (trace1) m_log.trace1 ("loadClass",  "(" + name + ", " + resolve + "): nest level " + m_nestLevel);
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        Class c = null;
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // first, check if this class has already been defined by this classloader
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // instance:
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        c = findLoadedClass (name);
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (c == null)
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            Class parentsVersion = null;
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_parent != null)
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    parentsVersion = m_parent.loadClass (name); // note: it is important that this does not init the class
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ((parentsVersion.getClassLoader () != m_parent) ||
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        ((m_forcedDelegationFilter == null) || m_forcedDelegationFilter.included (name)))
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // (a) m_parent itself decided to delegate: use parent's version
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // (b) the class was on the forced delegation list: use parent's version
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        c = parentsVersion;
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (trace1) m_log.trace1 ("loadClass", "using parent's version for [" + name + "]");
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (ClassNotFoundException cnfe)
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // if the class was on the forced delegation list, error out:
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ((m_forcedDelegationFilter == null) || m_forcedDelegationFilter.included (name))
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        throw cnfe;
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (c == null)
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // either (a) m_parent was null or (b) it could not load 'c'
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // or (c) it will define 'c' itself if allowed to. In any
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // of these cases I attempt to define my own version:
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    c = findClass (name);
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (ClassNotFoundException cnfe)
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // this is a difficult design point unless I resurrect the -lx option
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // and document how to use it [which will confuse most users anyway]
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // another alternative would be to see if parent's version is included by
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // the filter and print a warning; still, it does not help with JAXP etc
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (parentsVersion != null)
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        final boolean delegate = (m_throughDelegationFilter == null) || m_throughDelegationFilter.included (name);
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (delegate)
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            c = parentsVersion;
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            if (trace1) m_log.trace1 ("loadClass", "[delegation filter] using parent's version for [" + name + "]");
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        else
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            throw cnfe;
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    else
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                      throw cnfe;
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (c == null) throw new ClassNotFoundException (name);
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (resolve) resolveClass (c); // this never happens in J2SE JVMs
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return c;
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // TODO: remove this in the release build
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public final URL getResource (final String name)
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final boolean trace1 = m_log.atTRACE1 ();
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (trace1) m_log.trace1 ("getResource",  "(" + name + "): nest level " + m_nestLevel);
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final URL result = super.getResource (name);
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (trace1 && (result != null)) m_log.trace1 ("loadClass",  "[" + name + "] found in " + result);
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return result;
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    protected final Class findClass (final String name)
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws ClassNotFoundException
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final boolean trace1 = m_log.atTRACE1 ();
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (trace1) m_log.trace1 ("findClass",  "(" + name + "): nest level " + m_nestLevel);
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final boolean useClassCache = (m_cache != null);
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final ClassPathCacheEntry entry = useClassCache ? (ClassPathCacheEntry) m_cache.remove (name) : null;
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        byte [] bytes;
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        int length;
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        URL classURL = null;
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (entry != null) // cache hit
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            ++ m_cacheHits;
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // used cached class def bytes, no need to repeat disk I/O:
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            try
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                classURL = new URL (entry.m_srcURL);
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            catch (MalformedURLException murle) // this should never happen
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if ($assert.ENABLED)
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    murle.printStackTrace (System.out);
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            PoolEntry buf = null;
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            try
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                buf = acquirePoolEntry ();
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final ByteArrayOStream baos = buf.m_baos; // reset() has been called on this
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // the original class definition:
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                bytes = entry.m_bytes;
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                length = bytes.length;
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if ((m_hook != null) && m_hook.processClassDef (name, bytes, length, baos)) // note: this can overwrite 'bytes'
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // the instrumented class definition:
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    bytes = baos.getByteArray ();
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    length = baos.size ();
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (trace1) m_log.trace1 ("findClass",  "defining [cached] instrumented [" + name + "] {" + length + " bytes }");
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                else
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (trace1) m_log.trace1 ("findClass",  "defining [cached] [" + name + "] {" + length + " bytes }");
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                return defineClass (name, bytes, length, classURL);
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            catch (IOException ioe)
232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new ClassNotFoundException (name);
234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            finally
236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (buf != null) releasePoolEntry (buf);
238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else // cache miss
241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (useClassCache) ++ m_cacheMisses;
243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // .class files are not guaranteed to be loadable as resources;
245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // but if Sun's code does it...
246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String classResource = name.replace ('.', '/') + ".class";
247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // even thought normal delegation is disabled, this will find bootstrap classes:
249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            classURL = getResource (classResource); // important to hook into URLClassLoader's overload of this so that Class-Path manifest attributes are processed etc
250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (trace1 && (classURL != null)) m_log.trace1 ("findClass",  "[" + name + "] found in " + classURL);
252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (classURL == null)
254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                throw new ClassNotFoundException (name);
255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                InputStream in = null;
258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                PoolEntry buf = null;
259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    in = classURL.openStream ();
262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    buf = acquirePoolEntry ();
264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final ByteArrayOStream baos = buf.m_baos; // reset() has been called on this
265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    readFully (in, baos, buf.m_buf);
267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    in.close (); // don't keep the file handle across reentrant calls
268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    in = null;
269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // the original class definition:
271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    bytes = baos.getByteArray ();
272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    length = baos.size ();
273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    baos.reset (); // reuse this for processClassDef below
275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ((m_hook != null) && m_hook.processClassDef (name, bytes, length, baos)) // note: this can overwrite 'bytes'
277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // the instrumented class definition:
279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        bytes = baos.getByteArray ();
280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        length = baos.size ();
281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (trace1) m_log.trace1 ("findClass",  "defining instrumented [" + name + "] {" + length + " bytes }");
283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    else
285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (trace1) m_log.trace1 ("findClass",  "defining [" + name + "] {" + length + " bytes }");
287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    return defineClass (name, bytes, length, classURL);
290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (IOException ioe)
292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new ClassNotFoundException (name);
294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                finally
296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (buf != null) releasePoolEntry (buf);
298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (in != null) try { in.close (); } catch (Exception ignore) {}
299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void debugDump (final PrintWriter out)
305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (out != null)
307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            out.println (this + ": " + m_cacheHits + " class cache hits, " + m_cacheMisses + " misses");
309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final class PoolEntry
318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        PoolEntry (final int baosCapacity, final int bufSize)
320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_baos = new ByteArrayOStream (baosCapacity);
322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_buf = new byte [bufSize];
323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        void trim (final int baosCapacity, final int baosMaxCapacity)
326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (m_baos.capacity () > baosMaxCapacity)
328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_baos = new ByteArrayOStream (baosCapacity);
330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        ByteArrayOStream m_baos;
334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final byte [] m_buf;
335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    } // end of nested class
337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * 'srcURL' may be null
341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private Class defineClass (final String className, final byte [] bytes, final int length, final URL srcURL)
343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // support ProtectionDomains with non-null class source URLs:
345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // [however, disable anything related to sealing or signing]
346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final CodeSource csrc = new CodeSource (srcURL, (Certificate[])null);
348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // allow getPackage() to return non-null on the class we are about to
350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // define (however, don't bother emulating the original manifest info since
351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // we may be altering manifest content anyway):
352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final int lastDot = className.lastIndexOf ('.');
354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (lastDot >= 0)
355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String packageName = className.substring (0, lastDot);
357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final Package pkg = getPackage (packageName);
359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (pkg == null)
360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                definePackage (packageName,
362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               IAppConstants.APP_NAME, IAppConstants.APP_VERSION, IAppConstants.APP_COPYRIGHT,
363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               IAppConstants.APP_NAME, IAppConstants.APP_VERSION, IAppConstants.APP_COPYRIGHT,
364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                               srcURL);
365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return defineClass (className, bytes, 0, length, csrc);
369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static URL [] filesToURLs (final File [] classpath)
373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws MalformedURLException
374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((classpath == null) || (classpath.length == 0))
376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return EMPTY_URL_ARRAY;
377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final URL [] result = new URL [classpath.length];
379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int f = 0; f < result.length ; ++ f)
381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            result [f] = classpath [f].toURL (); // note: this does proper dir encoding
383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return result;
386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Reads the entire contents of a given stream into a flat byte array.
390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static void readFully (final InputStream in, final ByteArrayOStream out, final byte [] buf)
392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws IOException
393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int read; (read = in.read (buf)) >= 0; )
395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            out.write (buf, 0, read);
397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * not MT-safe; must be called from loadClass() only
402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private PoolEntry acquirePoolEntry ()
404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        PoolEntry result;
406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_nestLevel >= BAOS_POOL_SIZE)
408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            result = new PoolEntry (BAOS_INIT_SIZE, BAOS_INIT_SIZE);
410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            result = m_bufPool [m_nestLevel];
414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (result == null)
415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                result = new PoolEntry (BAOS_INIT_SIZE, BAOS_INIT_SIZE);
417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                m_bufPool [m_nestLevel] = result;
418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                result.m_baos.reset ();
422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        ++ m_nestLevel;
426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return result;
428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * not MT-safe; must be called from loadClass() only
432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private void releasePoolEntry (final PoolEntry buf)
434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (-- m_nestLevel < BAOS_POOL_SIZE)
436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            buf.trim (BAOS_INIT_SIZE, BAOS_MAX_SIZE);
438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final ClassLoader m_parent;
443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IInclExclFilter m_forcedDelegationFilter;
445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IInclExclFilter m_throughDelegationFilter;
446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final Map /* classJavaName:String -> ClassPathCacheEntry */ m_cache; // can be null
448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IClassLoadHook m_hook;
449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final PoolEntry [] m_bufPool;
450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final Logger m_log; // a loader instance is used concurrently but cached its log config at construction time
452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private int m_nestLevel;
454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private int m_cacheHits, m_cacheMisses;
456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int BAOS_INIT_SIZE = 32 * 1024;
458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int BAOS_MAX_SIZE = 1024 * 1024;
459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int BAOS_POOL_SIZE = 8;
460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final URL [] EMPTY_URL_ARRAY = new URL [0];
461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
464