Proxy.java revision b1396870f92135aa140bd2b86221768dea5bc11d
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.lang.reflect;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.ref.WeakReference;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashMap;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Map;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.WeakHashMap;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// BEGIN android-removed
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// import org.apache.harmony.luni.internal.reflect.ProxyClassFile;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// END android-removed
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code Proxy} defines methods for creating dynamic proxy classes and instances.
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A proxy class implements a declared set of interfaces and delegates method
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * invocations to an {@code InvocationHandler}.
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see InvocationHandler
36f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @since 1.3
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class Proxy implements Serializable {
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -2222568056686623797L;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // maps class loaders to created classes by interface names
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // to find previously created types
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int NextClassNameIndex = 0;
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The invocation handler on which the method calls are dispatched.
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected InvocationHandler h;
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unused")
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Proxy() {
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code Proxy} instance with the specified invocation
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * handler.
62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param h
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the invocation handler for the newly created proxy
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected Proxy(InvocationHandler h) {
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.h = h;
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the dynamically built {@code Class} for the specified interfaces.
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new {@code Class} when necessary. The order of the interfaces
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * is relevant. Invocations of this method with the same interfaces but
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * different order result in different generated classes. The interfaces
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * must be visible from the supplied class loader; no duplicates are
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * permitted. All non-public interfaces must be defined in the same package.
77f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param loader
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the class loader that will define the proxy class
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param interfaces
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            an array of {@code Class} objects, each one identifying an
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            interface that will be implemented by the returned proxy
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            class
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a proxy class that implements all of the interfaces referred to
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         in the contents of {@code interfaces}
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if any of the interface restrictions are violated
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if either {@code interfaces} or any of its elements are
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                {@code null}
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Class<?> getProxyClass(ClassLoader loader,
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?>... interfaces) throws IllegalArgumentException {
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // BEGIN android-note
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Changed parameter to be closer to the RI
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // END android-note
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check that interfaces are a valid array of visible interfaces
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (interfaces == null) {
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String commonPackageName = null;
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0, length = interfaces.length; i < length; i++) {
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?> next = interfaces[i];
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (next == null) {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new NullPointerException();
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String name = next.getName();
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!next.isInterface()) {
109b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                throw new IllegalArgumentException(name + " is not an interface");
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (loader != next.getClassLoader()) {
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                try {
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (next != Class.forName(name, false, loader)) {
114b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                        throw new IllegalArgumentException(name +
115b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                                " is not visible from class loader");
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } catch (ClassNotFoundException ex) {
118b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                    throw new IllegalArgumentException(name + " is not visible from class loader");
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int j = i + 1; j < length; j++) {
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (next == interfaces[j]) {
123b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                    throw new IllegalArgumentException(name + " appears more than once");
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!Modifier.isPublic(next.getModifiers())) {
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int last = name.lastIndexOf('.');
128f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String p = last == -1 ? "" : name.substring(0, last);
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (commonPackageName == null) {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    commonPackageName = p;
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (!commonPackageName.equals(p)) {
132b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                    throw new IllegalArgumentException("non-public interfaces must be " +
133b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes                            "in the same package");
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // search cache for matching proxy class using the class loader
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (loaderCache) {
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Map<String, WeakReference<Class<?>>> interfaceCache = loaderCache
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .get(loader);
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (interfaceCache == null) {
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                loaderCache
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        .put(
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                loader,
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                (interfaceCache = new HashMap<String, WeakReference<Class<?>>>()));
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            String interfaceKey = "";
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (interfaces.length == 1) {
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                interfaceKey = interfaces[0].getName();
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                StringBuilder names = new StringBuilder();
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int i = 0, length = interfaces.length; i < length; i++) {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    names.append(interfaces[i].getName());
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    names.append(' ');
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                interfaceKey = names.toString();
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?> newClass;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ref == null) {
164f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String nextClassName = "$Proxy" + NextClassNameIndex++;
165f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (commonPackageName != null && commonPackageName.length() > 0) {
166f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    nextClassName = commonPackageName + "." + nextClassName;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // BEGIN android-changed
169f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // byte[] classFileBytes = ProxyClassFile.generateBytes(
170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                //         nextClassName, interfaces);
171f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // newClass = defineClassImpl(loader, nextClassName.replace('.',
172f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                //         '/'), classFileBytes);
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (loader == null) {
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    loader = ClassLoader.getSystemClassLoader();
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newClass = generateProxy(nextClassName.replace('.', '/'),
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        interfaces, loader);
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // END android-changed
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Need a weak reference to the class so it can
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // be unloaded if the class loader is discarded
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                interfaceCache.put(interfaceKey, new WeakReference<Class<?>>(
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        newClass));
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (proxyCache) {
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // the value is unused
185f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    proxyCache.put(newClass, "");
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newClass = ref.get();
189f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\""
190f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                                        + "\nloaderCache=\"" + loaderCache + "\""
191f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                                        + "\nintfCache=\"" + interfaceCache + "\""
192f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                                        + "\nproxyCache=\"" + proxyCache + "\"";
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return newClass;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an instance of the dynamically built class for the specified
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * interfaces. Method invocations on the returned instance are forwarded to
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the specified invocation handler. The interfaces must be visible from the
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * supplied class loader; no duplicates are permitted. All non-public
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * interfaces must be defined in the same package.
204f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param loader
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the class loader that will define the proxy class
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param interfaces
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            an array of {@code Class} objects, each one identifying an
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            interface that will be implemented by the returned proxy
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            object
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param h
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the invocation handler that handles the dispatched method
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            invocations
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a new proxy object that delegates to the handler {@code h}
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if any of the interface restrictions are violated
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if the interfaces or any of its elements are null
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Object newProxyInstance(ClassLoader loader,
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Class<?>[] interfaces, InvocationHandler h)
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IllegalArgumentException {
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (h == null) {
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return getProxyClass(loader, interfaces).getConstructor(
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    new Class<?>[] { InvocationHandler.class }).newInstance(
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    new Object[] { h });
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (NoSuchMethodException ex) {
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw (InternalError) (new InternalError(ex.toString())
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .initCause(ex));
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalAccessException ex) {
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw (InternalError) (new InternalError(ex.toString())
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .initCause(ex));
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (InstantiationException ex) {
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw (InternalError) (new InternalError(ex.toString())
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .initCause(ex));
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (InvocationTargetException ex) {
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Throwable target = ex.getTargetException();
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw (InternalError) (new InternalError(target.toString())
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .initCause(target));
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether or not the specified class is a dynamically generated
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * proxy class.
249f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param cl
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the class
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the class is a proxy class, {@code false}
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if the class is {@code null}
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static boolean isProxyClass(Class<?> cl) {
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (cl == null) {
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (proxyCache) {
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return proxyCache.containsKey(cl);
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the invocation handler of the specified proxy instance.
268f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param proxy
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the proxy instance
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the invocation handler of the specified proxy instance
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *                if the supplied {@code proxy} is not a proxy object
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static InvocationHandler getInvocationHandler(Object proxy)
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IllegalArgumentException {
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isProxyClass(proxy.getClass())) {
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return ((Proxy) proxy).h;
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
282b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        throw new IllegalArgumentException("not a proxy instance");
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // BEGIN android-changed
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //private static native Class<?> defineClassImpl(ClassLoader classLoader,
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //        String className, byte[] classFileBytes);
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    native private static Class generateProxy(String name, Class[] interfaces,
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ClassLoader loader);
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The VM clones this method's descriptor when generating a proxy class.
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * There is no implementation.
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    native private static void constructorPrototype(InvocationHandler h);
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // END android-changed
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
299