All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com4j.ComMethod Maven / Gradle / Ivy

There is a newer version: 20110320
Show newest version
package com4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.nio.Buffer;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;



/**
 * Internal abstraction that represents a COM method invocation.
 *
 * 

* Instances hide the details of how to invoke a COM method. * (or a series of them.) * * @author Kohsuke Kawaguchi * @author Michael Schnell (scm, (C) 2008, [email protected]) */ abstract class ComMethod { /** The Java method that corresponds to the native COM method */ final protected Method method; /** * The array of default parameters of the COM methods * @see #defaultParameterIndex */ final protected Object[] defaultParameters; /** * The parameter indexes of default parameters. Each position in this array corresponds to a position in {@link #defaultParameters} * *

*

Example

* Let's assume the following values: *
     *  defaultParameterIndex = {2, 4};
     *  defaultParameters = {new Integer(3), "Hello"};
     *  
* In this example the second parameter of the {@link ComMethod} has a default value of new Integer(3) and the * forth parameter has a default value of "Hello". *

* @see #defaultParameters */ final protected int[] defaultParameterIndex; /** Array of NativeTypes that describe the parameters of the method */ final NativeType[] params; /** The parameter conversion codes passed to the native part of the invoke method */ final int[] paramConvs; /** The index in the parameters of the return value ([retval, out] value) */ final int returnIndex; /** True, if the [retval] parameters is [in, out] */ final boolean returnIsInOut; /** The value conversion code for the return value */ final NativeType returnConv; /** The Class objects of the parameters */ final Class[] paramTypes; /** The Type objects of the generic parameters */ final Type[] genericParamTypes; /** * Constructs a new ComMethod for the given {@link Method} * @param method The Method designed to be a ComMethod (annotations) */ public ComMethod(Method method){ this.method = method; //generate default values UseDefaultValues defValues = method.getAnnotation(UseDefaultValues.class); if(defValues != null){ defaultParameters = new Object[defValues.optParamIndex().length]; defaultParameterIndex = defValues.optParamIndex(); generateDefaultParameters(defValues); }else{ defaultParameters = new Object[0]; defaultParameterIndex = new int[0]; } MethodIntrospector mi = new MethodIntrospector(method); Annotation[][] pa = method.getParameterAnnotations(); int paramLen = pa.length; // retrieve information about the return value ReturnValue rt = method.getAnnotation(ReturnValue.class); if(rt!=null) { if(rt.index()==-1) returnIndex=pa.length; else returnIndex=rt.index(); returnIsInOut = rt.inout(); if(rt.type() == NativeType.Default){ returnConv = getDefaultConversion(method.getReturnType()); } else { returnConv = rt.type(); } } else { // guess the default if( method.getReturnType()==Void.TYPE ) { // no return type returnIndex = -1; returnIsInOut = false; returnConv = NativeType.Default; // unused } else { returnIndex = paramLen; returnIsInOut = false; returnConv = getDefaultConversion(method.getReturnType()); } } // retrieve information about the parameters Class[] paramTypesLocal = method.getParameterTypes(); Type[] genericParamTypesLocal = method.getGenericParameterTypes(); // Optional parameter int defValsCount = 0; if(defValues != null){ defValsCount = defValues.optParamIndex().length; } params = new NativeType[paramLen + defValsCount]; paramConvs = new int[paramLen + defValsCount]; paramTypes = new Class[paramLen + defValsCount]; genericParamTypes = new Type[paramLen + defValsCount]; // the "user visalbe" parameters of the Java interface for( int i=0; i,NativeType> defaultConversions = new HashMap, NativeType>(); static { defaultConversions.put( Iterator.class, NativeType.ComObject ); defaultConversions.put( GUID.class, NativeType.GUID ); defaultConversions.put( double.class, NativeType.Double ); defaultConversions.put( float.class, NativeType.Float ); defaultConversions.put( long.class, NativeType.Int64 ); defaultConversions.put( int.class, NativeType.Int32 ); defaultConversions.put( short.class, NativeType.Int16 ); defaultConversions.put( byte.class, NativeType.Int8 ); defaultConversions.put( boolean.class, NativeType.VariantBool ); defaultConversions.put( String.class, NativeType.BSTR ); defaultConversions.put( Object.class, NativeType.VARIANT_ByRef ); defaultConversions.put( Variant.class, NativeType.VARIANT_ByRef ); defaultConversions.put( Date.class, NativeType.Date ); } /** * Computes the default conversion for the given type. */ static NativeType getDefaultConversion(Type t) { if( t instanceof Class ) { Class c = (Class)t; NativeType r = defaultConversions.get(c); if(r!=null) return r; if(Com4jObject.class.isAssignableFrom(c)) return NativeType.ComObject; if(Enum.class.isAssignableFrom(c)) return NativeType.Int32; if(Buffer.class.isAssignableFrom(c)) return NativeType.PVOID; if(Calendar.class.isAssignableFrom(c)) return NativeType.Date; if(BigDecimal.class.isAssignableFrom(c)) return NativeType.Currency; if(c.isArray()) return NativeType.SafeArray; } if( t instanceof ParameterizedType ) { ParameterizedType p = (ParameterizedType) t; if( p.getRawType()==Holder.class ) { // let p=Holder Type v = p.getActualTypeArguments()[0]; Class c = (v instanceof Class) ? (Class)v : null; if(c!=null) { if(Com4jObject.class.isAssignableFrom(c)) return NativeType.ComObject_ByRef; if(String.class==c) return NativeType.BSTR_ByRef; if(Integer.class==c || Enum.class.isAssignableFrom(c)) return NativeType.Int32_ByRef; if(Boolean.class==c) return NativeType.VariantBool_ByRef; if(Buffer.class.isAssignableFrom(c)) return NativeType.PVOID_ByRef; } // if(v instanceof GenericArrayType){ // return NativeType.SafeArray_ByRef; // } } if( p.getRawType()==Iterator.class ) { return NativeType.ComObject; } } throw new IllegalAnnotationException("no default conversion available for "+t); } /** * Generates the default values for this ComMethod using the given {@link UseDefaultValues} annotation * @param defValues the annotation containing the information to generate the default values. */ protected void generateDefaultParameters(UseDefaultValues defValues){ int count = defValues.optParamIndex().length; NativeType[] nt = defValues.nativeType(); Variant.Type[] vt = defValues.variantType(); String[] literal = defValues.literal(); for (int i = 0; i < count; i++) { switch(nt[i]){ case Bool: case VariantBool: case VariantBool_ByRef: defaultParameters[i] = Boolean.parseBoolean(literal[i]); break; case BSTR: case BSTR_ByRef: case CSTR: case Unicode: defaultParameters[i] = literal[i]; break; case Double: case Double_ByRef: defaultParameters[i] = Double.parseDouble(literal[i]); break; case Float: case Float_ByRef: defaultParameters[i] = Float.parseFloat(literal[i]); break; case Int8: case Int8_ByRef: defaultParameters[i] = Byte.parseByte(literal[i]); break; case Int16: case Int16_ByRef: defaultParameters[i] = Short.parseShort(literal[i]); break; case Int32: case Int32_ByRef: defaultParameters[i] = Integer.parseInt(literal[i]); break; case Int64: case Int64_ByRef: defaultParameters[i] = Long.parseLong(literal[i]); break; case GUID: defaultParameters[i] = new GUID(literal[i]); break; case Currency: case Currency_ByRef: defaultParameters[i] = new BigDecimal(literal[i]); break; case VARIANT: Variant v = new Variant(); switch(vt[i]){ case VT_I1: case VT_UI1: v.set(Byte.parseByte(literal[i])); break; case VT_I2: case VT_UI2: v.set(Short.parseShort(literal[i])); break; case VT_I4: case VT_UI4: case VT_INT: case VT_UINT: v.set(Integer.parseInt(literal[i])); break; case VT_I8: v.set(Long.parseLong(literal[i])); break; case VT_R4: v.set(Float.parseFloat(literal[i])); break; case VT_R8: v.set(Double.parseDouble(literal[i])); break; case VT_BOOL: v.set(Boolean.parseBoolean(literal[i])); break; case VT_BSTR: v.set(literal[i]); break; case VT_EMPTY: v= new Variant(); break; case VT_ERROR: v.makeError((int)Long.parseLong(literal[i], 16)); break; // case VT_CY: ... default: throw new UnsupportedOperationException("Don't know how to parse literal " + literal[i] + " to an Java Object corresponding to Variant.Type." + vt[i].name()); } v.setType(vt[i]); defaultParameters[i] = v; break; default: throw new UnsupportedOperationException("Don't know how to parse literal " + literal[i] + " to an Java Object corresponding to NativeType." + nt[i].name()); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy