package controlP5; /** * controlP5 is a processing gui library. * * 2006-2012 by Andreas Schlegel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * @author Andreas Schlegel (http://www.sojamo.de) * @modified ##date## * @version ##version## * */ import java.lang.reflect.Method; import java.lang.reflect.Field; import java.security.AccessControlException; /** * The ControllerPlug is used to do all the reflection procedures to link a controller to a variable * or function inside your main application. * * @example use/ControlP5plugTo */ public class ControllerPlug { private Object _myObject; private String _myName; private Method _myMethod; private Field _myField; private int _myType = ControlP5Constants.INVALID; private Class< ? > _myParameterClass; private int _myParameterType = -1; private Object _myValue = null; private Class< ? >[] _myAcceptClassList; private Class< ? > _myEventMethodParameter = ControlEvent.class; public ControllerPlug( final Object theObject , final String theName , final int theType , final int theParameterType , Class< ? >[] theAcceptClassList ) { set( theObject , theName , theType , theParameterType , theAcceptClassList ); } ControllerPlug( Class< ? > param , final Object theObject , final String theName , final int theType , final int theParameterType ) { setEventMethodParameter( param ); set( theObject , theName , theType , theParameterType , null ); } void setEventMethodParameter( Class< ? > theClass ) { _myEventMethodParameter = theClass; } protected void set( Object theObject ) { set( theObject , getName( ) , getType( ) , getParameterType( ) , getAcceptClassList( ) ); } public void set( final Object theObject , final String theName , final int theType , final int theParameterType , final Class< ? >[] theAcceptClassList ) { _myObject = theObject; _myName = theName; _myType = theType; _myParameterType = theParameterType; _myAcceptClassList = theAcceptClassList; Class< ? > myClass = theObject.getClass( ); /* check for methods */ if ( _myType == ControlP5Constants.METHOD ) { try { Method[] myMethods = myClass.getMethods( ); for ( int i = 0 ; i < myMethods.length ; i++ ) { if ( ( myMethods[ i ].getName( ) ).equals( theName ) ) { if ( myMethods[ i ].getParameterTypes( ).length == 1 ) { for ( int j = 0 ; j < _myAcceptClassList.length ; j++ ) { if ( myMethods[ i ].getParameterTypes( )[ 0 ] == _myAcceptClassList[ j ] ) { _myParameterClass = myMethods[ i ].getParameterTypes( )[ 0 ]; break; } } } else if ( myMethods[ i ].getParameterTypes( ).length == 0 ) { _myParameterClass = null; break; } break; } } Class< ? >[] myArgs = ( _myParameterClass == null ) ? new Class[] { } : new Class[] { _myParameterClass }; _myMethod = myClass.getMethod( _myName , myArgs ); _myMethod.setAccessible( true ); } catch ( SecurityException e ) { printSecurityWarning( e ); } catch ( NoSuchMethodException e ) { if ( _myParameterClass != CallbackEvent.class ) { ControlP5.logger( ).warning( " plug() failed. If function " + theName + " does exist, make it public. " + e ); } } /* check for controlEvent */ } else if ( _myType == ControlP5Constants.EVENT ) { try { _myMethod = _myObject.getClass( ).getMethod( _myName , new Class[] { _myEventMethodParameter } ); _myMethod.setAccessible( true ); _myParameterClass = _myEventMethodParameter; } catch ( SecurityException e ) { printSecurityWarning( e ); } catch ( NoSuchMethodException e ) { if ( _myEventMethodParameter != CallbackEvent.class ) { ControlP5.logger( ).warning( " plug() failed " + _myParameterClass + ". If function " + theName + " does exist, make it public. " + e ); } } /* check for fields */ } else if ( _myType == ControlP5Constants.FIELD ) { Field[] myFields = ControlBroadcaster.getFieldsFor( myClass ); for ( int i = 0 ; i < myFields.length ; i++ ) { if ( myFields[ i ].getName( ).equals( _myName ) ) { _myParameterClass = myFields[ i ].getType( ); } } if ( _myParameterClass != null ) { /** * note. when running in applet mode. for some reason setAccessible(true) works for * methods but not for fields. theAccessControlException is thrown. therefore, make * fields in your code public. */ try { _myField = myClass.getDeclaredField( _myName ); try { _myField.setAccessible( true ); } catch ( java.security.AccessControlException e ) { printSecurityWarning( e ); } try { _myValue = ( _myField.get( theObject ) ); } catch ( Exception ex ) { printSecurityWarning( ex ); } } catch ( NoSuchFieldException e ) { ControlP5.logger( ).warning( e.toString( ) ); } } } } private void printSecurityWarning( Exception e ) { // AccessControlException required for applets. if ( e.getClass( ).equals( AccessControlException.class ) ) { ControlP5.isApplet = true; ControlP5.logger( ).warning( "You are probably running in applet mode.\n" + "make sure fields and methods in your code are public.\n" + e ); } } protected Object getValue( ) { return _myValue; } protected Object getObject( ) { return _myObject; } protected String getName( ) { return _myName; } protected int getType( ) { return _myType; } protected int getParameterType( ) { return _myParameterType; } protected Class< ? >[] getAcceptClassList( ) { return _myAcceptClassList; } protected Class< ? > getClassType( ) { return _myParameterClass; } protected boolean checkType( int theType ) { return _myType == theType; } protected boolean checkName( String theName ) { return ( _myName.equals( theName ) ); } private Object get( float theValue ) { if ( _myParameterClass == float.class ) { return new Float( theValue ); } else if ( _myParameterClass == int.class ) { return new Integer( ( int ) theValue ); } else if ( _myParameterClass == boolean.class ) { return ( theValue > 0.5 ) ? new Boolean( true ) : new Boolean( false ); } else { return null; } } protected Object getFieldParameter( float theValue ) { return get( theValue ); } protected Object[] getMethodParameter( float theValue ) { return new Object[] { get( theValue ) }; } protected Method getMethod( ) { return _myMethod; } protected Field getField( ) { return _myField; } static public boolean checkPlug( Object theObject , String thePlugName , Class< ? >[] theArgs ) { try { theObject.getClass( ).getMethod( thePlugName , theArgs ); return true; } catch ( Exception e ) { return false; } } @Deprecated protected Class< ? > classType( ) { return _myParameterClass; } @Deprecated protected Object value( ) { return _myValue; } @Deprecated protected Object object( ) { return _myObject; } @Deprecated protected String name( ) { return _myName; } @Deprecated protected int type( ) { return _myType; } @Deprecated protected int parameterType( ) { return _myParameterType; } @Deprecated protected Class< ? >[] acceptClassList( ) { return _myAcceptClassList; } }