/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package org.googlecode.perftrace.javassist.util.proxy;
import java.lang.reflect.Method;
import java.io.Serializable;
/**
* Runtime support routines that the classes generated by ProxyFactory use.
*
* @see ProxyFactory
*/
public class RuntimeSupport {
/**
* A method handler that only executes a method.
*/
public static MethodHandler default_interceptor = new DefaultMethodHandler();
static class DefaultMethodHandler implements MethodHandler, Serializable {
public Object invoke(Object self, Method m,
Method proceed, Object[] args)
throws Exception
{
return proceed.invoke(self, args);
}
};
/**
* Finds two methods specified by the parameters and stores them
* into the given array.
*
* @throws RuntimeException if the methods are not found.
* @see org.googlecode.perftrace.javassist.util.proxy.ProxyFactory
*/
public static void find2Methods(Class clazz, String superMethod,
String thisMethod, int index,
String desc, java.lang.reflect.Method[] methods)
{
methods[index + 1] = thisMethod == null ? null
: findMethod(clazz, thisMethod, desc);
methods[index] = findSuperMethod(clazz, superMethod, desc);
}
/**
* Finds a method with the given name and descriptor.
* It searches only the class of self.
*
* @throws RuntimeException if the method is not found.
*/
public static Method findMethod(Class clazz, String name, String desc) {
Method m = findMethod2(clazz, name, desc);
if (m == null)
error(clazz, name, desc);
return m;
}
/**
* Finds a method that has the given name and descriptor and is declared
* in the super class.
*
* @throws RuntimeException if the method is not found.
*/
public static Method findSuperMethod(Class clazz, String name, String desc) {
Method m = findSuperMethod2(clazz.getSuperclass(), name, desc);
if (m == null)
m = searchInterfaces(clazz, name, desc);
if (m == null)
error(clazz, name, desc);
return m;
}
private static void error(Class clazz, String name, String desc) {
throw new RuntimeException("not found " + name + ":" + desc
+ " in " + clazz.getName());
}
private static Method findSuperMethod2(Class clazz, String name, String desc) {
Method m = findMethod2(clazz, name, desc);
if (m != null)
return m;
Class superClass = clazz.getSuperclass();
if (superClass != null) {
m = findSuperMethod2(superClass, name, desc);
if (m != null)
return m;
}
return searchInterfaces(clazz, name, desc);
}
private static Method searchInterfaces(Class clazz, String name, String desc) {
Method m = null;
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
m = findSuperMethod2(interfaces[i], name, desc);
if (m != null)
return m;
}
return m;
}
private static Method findMethod2(Class clazz, String name, String desc) {
Method[] methods = SecurityActions.getDeclaredMethods(clazz);
int n = methods.length;
for (int i = 0; i < n; i++)
if (methods[i].getName().equals(name)
&& makeDescriptor(methods[i]).equals(desc))
return methods[i];
return null;
}
/**
* Makes a descriptor for a given method.
*/
public static String makeDescriptor(Method m) {
Class[] params = m.getParameterTypes();
return makeDescriptor(params, m.getReturnType());
}
/**
* Makes a descriptor for a given method.
*
* @param params parameter types.
* @param retType return type.
*/
public static String makeDescriptor(Class[] params, Class retType) {
StringBuffer sbuf = new StringBuffer();
sbuf.append('(');
for (int i = 0; i < params.length; i++)
makeDesc(sbuf, params[i]);
sbuf.append(')');
if (retType != null)
makeDesc(sbuf, retType);
return sbuf.toString();
}
/**
* Makes a descriptor for a given method.
*
* @param params the descriptor of parameter types.
* @param retType return type.
*/
public static String makeDescriptor(String params, Class retType) {
StringBuffer sbuf = new StringBuffer(params);
makeDesc(sbuf, retType);
return sbuf.toString();
}
private static void makeDesc(StringBuffer sbuf, Class type) {
if (type.isArray()) {
sbuf.append('[');
makeDesc(sbuf, type.getComponentType());
}
else if (type.isPrimitive()) {
if (type == Void.TYPE)
sbuf.append('V');
else if (type == Integer.TYPE)
sbuf.append('I');
else if (type == Byte.TYPE)
sbuf.append('B');
else if (type == Long.TYPE)
sbuf.append('J');
else if (type == Double.TYPE)
sbuf.append('D');
else if (type == Float.TYPE)
sbuf.append('F');
else if (type == Character.TYPE)
sbuf.append('C');
else if (type == Short.TYPE)
sbuf.append('S');
else if (type == Boolean.TYPE)
sbuf.append('Z');
else
throw new RuntimeException("bad type: " + type.getName());
}
else
sbuf.append('L').append(type.getName().replace('.', '/'))
.append(';');
}
/**
* Converts a proxy object to an object that is writable to an
* object stream. This method is called by <code>writeReplace()</code>
* in a proxy class.
*
* @since 3.4
*/
public static SerializedProxy makeSerializedProxy(Object proxy)
throws java.io.InvalidClassException
{
Class clazz = proxy.getClass();
MethodHandler methodHandler = null;
if (proxy instanceof ProxyObject)
methodHandler = ((ProxyObject)proxy).getHandler();
else if (proxy instanceof Proxy)
methodHandler = ProxyFactory.getHandler((Proxy)proxy);
return new SerializedProxy(clazz, ProxyFactory.getFilterSignature(clazz), methodHandler);
}
}