1 package com4j; 2 3 import java.lang.annotation.Annotation ; 4 import java.lang.reflect.Method ; 5 import java.lang.reflect.ParameterizedType ; 6 import java.lang.reflect.Type ; 7 import java.nio.Buffer ; 8 import java.util.Iterator ; 9 import java.util.Calendar ; 10 import java.util.Date ; 11 import java.util.Map ; 12 import java.util.HashMap ; 13 14 17 final class MethodInfo { 18 19 final Method method; 20 21 final int vtIndex; 22 final int[] paramConvs; 24 final NativeType[] params; 25 final int returnIndex; 26 final boolean returnIsInOut; 27 final NativeType returnConv; 28 final Class <?>[] paramTypes; 29 final Type [] genericParamTypes; 30 31 MethodInfo( Method m ) { 32 method = m; 33 34 VTID vtid = m.getAnnotation(VTID.class); 35 if(vtid==null) 36 throw new IllegalAnnotationException("@VTID is missing: "+m.toGenericString()); 37 vtIndex = vtid.value(); 38 39 Annotation [][] pa = m.getParameterAnnotations(); 40 int paramLen = pa.length; 41 42 43 ReturnValue rt = m.getAnnotation(ReturnValue.class); 44 if(rt!=null) { 45 if(rt.index()==-1) returnIndex=pa.length; 46 else returnIndex=rt.index(); 47 returnIsInOut = rt.inout(); 48 returnConv = rt.type(); 49 } else { 50 if( method.getReturnType()==Void.TYPE ) { 52 returnIndex = -1; 54 returnIsInOut = false; 55 returnConv = NativeType.Default; } else { 57 returnIndex = paramLen; 58 returnIsInOut = false; 59 returnConv = getDefaultConversion(method.getReturnType()); 60 } 61 } 62 63 Type [] javaParamTypes = m.getGenericParameterTypes(); 64 65 paramTypes = m.getParameterTypes(); 66 genericParamTypes = m.getGenericParameterTypes(); 67 paramConvs = new int[paramLen]; 68 params = new NativeType[paramLen]; 69 for( int i=0; i<paramLen; i++ ) { 70 NativeType n=null; 71 for( Annotation a : pa[i] ) 72 if( a instanceof MarshalAs ) 73 n = ((MarshalAs)a).value(); 74 if(n==null) { 75 n = getDefaultConversion(javaParamTypes[i]); 77 } 78 params[i] = n; 79 paramConvs[i] = n.code; 80 } 81 } 82 83 Object invoke( int ptr, Object [] args ) { 84 for( int i=0; i<args.length; i++ ) 85 args[i] = params[i].massage(args[i]); 86 87 try { 88 Object r = Native.invoke( ptr, vtIndex, args, paramConvs, 89 method.getReturnType(), returnIndex, returnIsInOut, returnConv.code ); 90 return returnConv.unmassage(method.getReturnType(), method.getGenericReturnType(), r); 91 } finally { 92 for( int i=0; i<args.length; i++ ) 93 args[i] = params[i].unmassage(paramTypes[i], genericParamTypes[i], args[i]); 94 } 95 } 96 97 98 private static final Map <Class ,NativeType> defaultConversions = new HashMap <Class , NativeType>(); 99 100 static { 101 defaultConversions.put( Iterator .class, NativeType.ComObject ); 102 defaultConversions.put( GUID.class, NativeType.GUID ); 103 defaultConversions.put( double.class, NativeType.Double ); 104 defaultConversions.put( float.class, NativeType.Float ); 105 defaultConversions.put( int.class, NativeType.Int32 ); 106 defaultConversions.put( short.class, NativeType.Int16 ); 107 defaultConversions.put( byte.class, NativeType.Int8 ); 108 defaultConversions.put( boolean.class, NativeType.VariantBool ); 109 defaultConversions.put( String .class, NativeType.BSTR ); 110 defaultConversions.put( Object .class, NativeType.VARIANT_ByRef ); 111 defaultConversions.put( Variant.class, NativeType.VARIANT_ByRef ); 112 defaultConversions.put( Date .class, NativeType.Date ); 113 } 114 115 118 private static NativeType getDefaultConversion(Type t) { 119 if( t instanceof Class ) { 120 Class <?> c = (Class <?>)t; 121 NativeType r = defaultConversions.get(c); 122 if(r!=null) return r; 123 124 if(Com4jObject.class.isAssignableFrom(c)) 125 return NativeType.ComObject; 126 if(Enum .class.isAssignableFrom(c)) 127 return NativeType.Int32; 128 if(Buffer .class.isAssignableFrom(c)) 129 return NativeType.PVOID; 130 if(Calendar .class.isAssignableFrom(c)) 131 return NativeType.Date; 132 } 133 134 if( t instanceof ParameterizedType ) { 135 ParameterizedType p = (ParameterizedType ) t; 136 if( p.getRawType()==Holder.class ) { 137 Type v = p.getActualTypeArguments()[0]; 139 if( v instanceof Class && Com4jObject.class.isAssignableFrom((Class <?>)v)) 140 return NativeType.ComObject_ByRef; 141 if(String .class==v) 142 return NativeType.BSTR_ByRef; 143 if(Integer .class==v) 144 return NativeType.Int32_ByRef; 145 } 146 if( p.getRawType()==Iterator .class ) { 147 return NativeType.ComObject; 148 } 149 } 150 151 throw new IllegalAnnotationException("no default conversion available for "+t); 152 } 153 154 } 155 | Popular Tags |