001: /*
002: * Javassist, a Java-bytecode translator toolkit.
003: * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
004: *
005: * The contents of this file are subject to the Mozilla Public License Version
006: * 1.1 (the "License"); you may not use this file except in compliance with
007: * the License. Alternatively, the contents of this file may be used under
008: * the terms of the GNU Lesser General Public License Version 2.1 or later.
009: *
010: * Software distributed under the License is distributed on an "AS IS" basis,
011: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
012: * for the specific language governing rights and limitations under the
013: * License.
014: */
015:
016: package javassist.util.proxy;
017:
018: import java.lang.reflect.Method;
019: import java.io.Serializable;
020:
021: /**
022: * Runtime support routines that the classes generated by ProxyFactory use.
023: *
024: * @see ProxyFactory
025: */
026: public class RuntimeSupport {
027: /**
028: * A method handler that only executes a method.
029: */
030: public static MethodHandler default_interceptor = new DefaultMethodHandler();
031:
032: static class DefaultMethodHandler implements MethodHandler,
033: Serializable {
034: public Object invoke(Object self, Method m, Method proceed,
035: Object[] args) throws Exception {
036: return proceed.invoke(self, args);
037: }
038: };
039:
040: /**
041: * Finds a method with the given name and descriptor.
042: * It searches only the class of self.
043: *
044: * @throws RuntimeException if the method is not found.
045: */
046: public static Method findMethod(Object self, String name,
047: String desc) {
048: Method m = findMethod2(self.getClass(), name, desc);
049: if (m == null)
050: error(self, name, desc);
051:
052: return m;
053: }
054:
055: /**
056: * Finds a method that has the given name and descriptor and is declared
057: * in the super class.
058: *
059: * @throws RuntimeException if the method is not found.
060: */
061: public static Method findSuperMethod(Object self, String name,
062: String desc) {
063: Class clazz = self.getClass();
064: Method m = findSuperMethod2(clazz.getSuperclass(), name, desc);
065: if (m == null)
066: m = searchInterfaces(clazz, name, desc);
067:
068: if (m == null)
069: error(self, name, desc);
070:
071: return m;
072: }
073:
074: private static void error(Object self, String name, String desc) {
075: throw new RuntimeException("not found " + name + ":" + desc
076: + " in " + self.getClass().getName());
077: }
078:
079: private static Method findSuperMethod2(Class clazz, String name,
080: String desc) {
081: Method m = findMethod2(clazz, name, desc);
082: if (m != null)
083: return m;
084:
085: Class super Class = clazz.getSuperclass();
086: if (super Class != null) {
087: m = findSuperMethod2(super Class, name, desc);
088: if (m != null)
089: return m;
090: }
091:
092: return searchInterfaces(clazz, name, desc);
093: }
094:
095: private static Method searchInterfaces(Class clazz, String name,
096: String desc) {
097: Method m = null;
098: Class[] interfaces = clazz.getInterfaces();
099: for (int i = 0; i < interfaces.length; i++) {
100: m = findSuperMethod2(interfaces[i], name, desc);
101: if (m != null)
102: return m;
103: }
104:
105: return m;
106: }
107:
108: private static Method findMethod2(Class clazz, String name,
109: String desc) {
110: Method[] methods = clazz.getDeclaredMethods();
111: int n = methods.length;
112: for (int i = 0; i < n; i++)
113: if (methods[i].getName().equals(name)
114: && makeDescriptor(methods[i]).equals(desc))
115: return methods[i];
116:
117: return null;
118: }
119:
120: /**
121: * Makes a descriptor for a given method.
122: */
123: public static String makeDescriptor(Method m) {
124: Class[] params = m.getParameterTypes();
125: return makeDescriptor(params, m.getReturnType());
126: }
127:
128: /**
129: * Makes a descriptor for a given method.
130: *
131: * @param params parameter types.
132: * @param retType return type.
133: */
134: public static String makeDescriptor(Class[] params, Class retType) {
135: StringBuffer sbuf = new StringBuffer();
136: sbuf.append('(');
137: for (int i = 0; i < params.length; i++)
138: makeDesc(sbuf, params[i]);
139:
140: sbuf.append(')');
141: makeDesc(sbuf, retType);
142: return sbuf.toString();
143: }
144:
145: private static void makeDesc(StringBuffer sbuf, Class type) {
146: if (type.isArray()) {
147: sbuf.append('[');
148: makeDesc(sbuf, type.getComponentType());
149: } else if (type.isPrimitive()) {
150: if (type == Void.TYPE)
151: sbuf.append('V');
152: else if (type == Integer.TYPE)
153: sbuf.append('I');
154: else if (type == Byte.TYPE)
155: sbuf.append('B');
156: else if (type == Long.TYPE)
157: sbuf.append('J');
158: else if (type == Double.TYPE)
159: sbuf.append('D');
160: else if (type == Float.TYPE)
161: sbuf.append('F');
162: else if (type == Character.TYPE)
163: sbuf.append('C');
164: else if (type == Short.TYPE)
165: sbuf.append('S');
166: else if (type == Boolean.TYPE)
167: sbuf.append('Z');
168: else
169: throw new RuntimeException("bad type: "
170: + type.getName());
171: } else
172: sbuf.append('L').append(type.getName().replace('.', '/'))
173: .append(';');
174: }
175:
176: /**
177: * Converts a proxy object to an object that is writable to an
178: * object stream. This method is called by <code>writeReplace()</code>
179: * in a proxy class.
180: *
181: * @since 3.4
182: */
183: public static SerializedProxy makeSerializedProxy(Object proxy)
184: throws java.io.InvalidClassException {
185: Class clazz = proxy.getClass();
186: return new SerializedProxy(clazz,
187: ProxyFactory.getFilter(clazz), ProxyFactory
188: .getHandler(clazz));
189: }
190: }
|