/* * PkgInvoker -- * * This class is used for the java::* commands to gain access to * package protected and protected members of a Java package. * * Copyright (c) 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * * RCS: @(#) $Id: PkgInvoker.java,v 1.1.1.1 1998/10/14 21:09:15 cvsadmin Exp $ * */ package tcl.lang.reflect; import java.lang.reflect.*; import java.util.*; /* * This class is used for the java::* commands to gain access to * package protected and protected members of a Java package. * * Normally, the java::* command can only access public members of * public classes inside any package. With the help of the PkgInvoker * class, the java::* command can access any member (constructor, * method, field or property) of any class in a package as long as the * member is not explicitly declared "private" * * The ability for Tcl to access protected members is desirable when * we use Tcl to perform "white-box" testing on the methods of a Java * package. * * To grant Tcl access to protected members of a package, do the * following: * * + Create a subclass of PkgInvoker, give it the name * "TclPkgInvoker", declare it public and place it inside the * said package. * * + Give your TclPkgInvoker class a public constructor with * no arguments. * * + Cut-and-paste the definitions of the following functions into * TclPkgInvoker class: invokeMethod, invokeConstructor, * getField and setField. * * An example of using PkgInvoker can be found in the directory * src/tests/pkg1 and the file tests/common/PkgInvoker.test * */ public class PkgInvoker { /* * PkgInvokers of the packages that we have already visited are stored * in this hashtable. They key is the String name of a package. */ static Hashtable cachedInvokers = new Hashtable(); /* * This is the default invoker to use if a package doesn't include a * proper TclPkgInvoker class. This means only the public members * of the public classes of that package can be accessed diretly * from Tcl. */ static PkgInvoker defaultInvoker = new PkgInvoker(); /* *---------------------------------------------------------------------- * * invokeConstructor -- * * Invoke the given constructor with the arguments. * * Results: * The new object instance returned by the constructor. * * Side effects: * The constructor may have arbitraty side effects. * *---------------------------------------------------------------------- */ public Object invokeConstructor( Constructor constructor, // The constructor to invoke. Object args[]) // Arguments for the constructor. throws InstantiationException, // Standard exceptions thrown by IllegalAccessException, // Constructor.newInstance. IllegalArgumentException, InvocationTargetException { return constructor.newInstance(args); } /* *---------------------------------------------------------------------- * * invokeMethod -- * * Invoke the given method of the obj with the arguments. * * Results: * The value returned by the method. * * Side effects: * The method may have arbitraty side effects. * *---------------------------------------------------------------------- */ public Object invokeMethod( Method method, // The method to invoke. Object obj, // The object associated with the method. // May be null if the method is static. Object args[]) // The arguments for the method. throws IllegalAccessException, // Standard exceptions throw by Method.Invoke. IllegalArgumentException, InvocationTargetException { return method.invoke(obj, args); } /* *---------------------------------------------------------------------- * * getField -- * * Query the value of the given field. * * Results: * The value of the field. * * Side effects: * None. * *---------------------------------------------------------------------- */ public Object getField( Field field, // The field to query. Object obj) // The object that owns the field. May be // null for static fields. throws IllegalArgumentException, // Standard exceptions thrown by Field.get(). IllegalAccessException { return field.get(obj); } /* *---------------------------------------------------------------------- * * setField -- * * Modify the value of the given field. * * Results: * None. * * Side effects: * When successful, the field is modified to be the new value. * *---------------------------------------------------------------------- */ public void setField( Field field, // The field to modify. Object obj, // The object that owns the field. May be // null for static fields. Object value) // New value for the field. throws IllegalArgumentException, // Standard exceptions thrown by Field.set(). IllegalAccessException { field.set(obj, value); } /* *---------------------------------------------------------------------- * * getPkgInvoker -- * * Returns the PkgInvoker for the package that includes the given * class. * * Results: * An instance of the PkgInvoker which is included in the package, * or defaultInvoker if the package doesn't include a proper * PkgInvoker. * * Side effects: * The returned value is also stored in a hashtable for faster * access in the future. * *---------------------------------------------------------------------- */ public static final PkgInvoker getPkgInvoker( Class cls) // Query the PkgInvoker of the package // that owns this class. { String clsName = cls.getName(); int index = clsName.lastIndexOf('.'); String pkg; if (index == -1) { pkg = ""; } else { pkg = clsName.substring(0, index); } PkgInvoker invoker = (PkgInvoker)cachedInvokers.get(pkg); if (invoker == null) { try { Class invCls = Class.forName(pkg + ".TclPkgInvoker"); invoker = (PkgInvoker)(invCls.newInstance()); } catch (Exception e) { /* * The package doesn't include a PkgInvoker class. We use * the default invoker, which means we can't invoke * any of the protected members inside this package. */ invoker = defaultInvoker; } if (invoker == null) { invoker = defaultInvoker; } cachedInvokers.put(pkg, invoker); } return invoker; } } // end PkgInvoker