001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.bytecode;
005:
006: import com.tc.asm.ClassAdapter;
007: import com.tc.asm.ClassVisitor;
008: import com.tc.asm.MethodVisitor;
009: import com.tc.asm.Opcodes;
010: import com.tc.asm.Type;
011: import com.tc.exception.TCRuntimeException;
012: import com.tc.util.runtime.Vm;
013:
014: import java.util.HashSet;
015: import java.util.Set;
016:
017: public class JavaLangReflectArrayAdapter extends ClassAdapter implements
018: Opcodes, ClassAdapterFactory {
019: private final static Set nonNativeMethods = new HashSet(2);
020: private final static Set excludeMethods = new HashSet(9);
021: private final static Set includedPrivateMethods = new HashSet(1);
022:
023: static {
024: nonNativeMethods.add("newInstance");
025: nonNativeMethods.add("<init>");
026: // the IBM JDK just delegates to their own setImpl native version
027: if (Vm.isIBM()) {
028: nonNativeMethods.add("set");
029: includedPrivateMethods.add("setImpl");
030: }
031:
032: excludeMethods.add("getLength");
033: excludeMethods.add("getByte");
034: excludeMethods.add("getBoolean");
035: excludeMethods.add("getChar");
036: excludeMethods.add("getDouble");
037: excludeMethods.add("getFloat");
038: excludeMethods.add("getInt");
039: excludeMethods.add("getLong");
040: excludeMethods.add("getShort");
041: }
042:
043: public JavaLangReflectArrayAdapter() {
044: super (null);
045: }
046:
047: private JavaLangReflectArrayAdapter(ClassVisitor cv,
048: ClassLoader caller) {
049: super (cv);
050: }
051:
052: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
053: return new JavaLangReflectArrayAdapter(visitor, loader);
054: }
055:
056: private boolean isNative(int access) {
057: return (access & Opcodes.ACC_NATIVE) == Opcodes.ACC_NATIVE;
058: }
059:
060: private boolean isPrivate(int access) {
061: return (access & Opcodes.ACC_PRIVATE) == Opcodes.ACC_PRIVATE;
062: }
063:
064: public MethodVisitor visitMethod(int access, String name,
065: String description, String signature, String[] exceptions) {
066: if (!isNative(access)) {
067: if (!nonNativeMethods.contains(name)) {
068: throw new TCRuntimeException(
069: "Unexpected non-native method: " + name
070: + description);
071: } else {
072: return super .visitMethod(access, name, description,
073: signature, exceptions);
074: }
075: }
076:
077: if (isPrivate(access) && !includedPrivateMethods.contains(name)) {
078: return super .visitMethod(access, name, description,
079: signature, exceptions);
080: } else if (isNative(access) && !excludeMethods.contains(name)) {
081: MethodVisitor mv = super .visitMethod(access
082: ^ Opcodes.ACC_NATIVE, name, description, signature,
083: exceptions);
084: addArrayUtilMethodCode(mv, name, description);
085: return null;
086: } else {
087: return super .visitMethod(access, name, description,
088: signature, exceptions);
089: }
090: }
091:
092: private void addArrayUtilMethodCode(MethodVisitor mv,
093: String methodName, String description) {
094: mv.visitCode();
095:
096: Type[] params = Type.getArgumentTypes(description);
097: Type returnType = Type.getReturnType(description);
098: for (int i = 0; i < params.length; i++) {
099: mv.visitVarInsn(params[i].getOpcode(ILOAD), i);
100: }
101: mv.visitMethodInsn(INVOKESTATIC, ManagerUtil.CLASS, methodName,
102: description);
103: mv.visitInsn(returnType.getOpcode(IRETURN));
104: mv.visitMaxs(0, 0);
105: mv.visitEnd();
106: }
107:
108: }
|