Mercurial > hg > octave-nkf
view scripts/java/org/octave/ClassHelper.java @ 15746:da26f72408a7
update copyright statements in newly added java files
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 07 Dec 2012 16:14:49 -0500 |
parents | acf0addfc610 |
children | 6e39fe7992d9 |
line wrap: on
line source
/* Copyright (C) 2007 Michael Goffioul ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; If not, see <http://www.gnu.org/licenses/>. */ package org.octave; import java.lang.reflect.*; public class ClassHelper { private static OctClassLoader loader; static { ClassLoader l = ClassHelper.class.getClassLoader (); loader = ( l instanceof OctClassLoader ? ( OctClassLoader ) l : new OctClassLoader ( l ) ); } /** * Add the given path to the classpath. * @param name String - path to addd to the classpath * @return boolean - true if the given path exists and was added to the classpath. * @throws Exception */ public static boolean addClassPath ( String name ) throws Exception { boolean found = false; java.io.File f = new java.io.File ( name ); if ( f.exists () ) { loader.addClassPath ( name ); found = true; } return ( found ); } // new -MH- /** * * @param name String - path to remove from classpath. * @return boolean - true if the given path existed in the classpath before it was removed. * @throws Exception */ public static boolean removeClassPath ( String name ) throws Exception { boolean found = false; java.io.File f = new java.io.File ( name ); java.net.URL urlToRemove = f.toURI ().toURL (); // save urls in current class path java.net.URL[] urls = loader.getURLs (); // create a completely new class loader because java.net.URLClassLoader has no removeClassPath() method ClassLoader l = ClassHelper.class.getClassLoader (); loader = ( l instanceof OctClassLoader ? ( OctClassLoader ) l : new OctClassLoader ( l ) ); // add the previous urls back, except for the one for ( int i = 0; i < urls.length; i++ ) { java.net.URL url = urls[i]; if ( !url.equals ( urlToRemove ) ) { loader.addURL ( url ); } else { // path to remove found = true; } } return ( found ); } public static String getClassPath () { StringBuffer buf = new StringBuffer (); String pathSep = System.getProperty ( "path.separator" ); java.net.URL[] urls = loader.getURLs (); for ( int i = 0; i < urls.length; i++ ) { try { java.io.File f = new java.io.File ( urls[i].toURI () ); if ( buf.length () > 0 ) { buf.append ( pathSep ); } buf.append ( f.toString () ); } catch ( java.net.URISyntaxException ex ) {} } return buf.toString (); } // new -MH- // return list of methods for given class name public static String getMethods ( String classname ) throws ClassNotFoundException { return ( getMethods ( Class.forName ( classname ) ) ); } // new -MH- // return list of methods for given class instance public static String getMethods ( Object obj ) throws ClassNotFoundException { return ( getMethods ( obj.getClass () ) ); } // new -MH- // return list of methods for given class public static String getMethods ( Class klass ) { StringBuffer sb = new StringBuffer (); Method theMethod[] = klass.getMethods (); for ( int i = 0; i < theMethod.length; i++ ) { if ( i > 0 ) { sb.append ( ";" ); } sb.append ( theMethod[i].getReturnType ().getCanonicalName () ); sb.append ( " " ); sb.append ( theMethod[i].getName () ); sb.append ( "(" ); Class theParameter[] = theMethod[i].getParameterTypes (); for ( int j = 0; j < theParameter.length; j++ ) { if ( j > 0 ) { sb.append ( ", " ); } sb.append ( theParameter[j].getCanonicalName () ); } sb.append ( ")" ); Class theExceptions[] = theMethod[i].getExceptionTypes (); if ( theExceptions.length > 0 ) { sb.append ( " throws " ); for ( int j = 0; j < theExceptions.length; j++ ) { if ( j > 0 ) { sb.append ( ", " ); } sb.append ( theExceptions[j].getCanonicalName () ); } } } return ( sb.toString () ); } // new -MH- // return list of fields for given class public static String getFields ( Class klass ) { StringBuffer sb = new StringBuffer (); Field theField[] = klass.getFields (); for ( int i = 0; i < theField.length; i++ ) { if ( i > 0 ) { sb.append ( ";" ); } sb.append ( theField[i].toString () ); } return ( sb.toString () ); } // new -MH- // return list of fields for given class name public static String getFields ( String classname ) throws ClassNotFoundException { return ( getFields ( Class.forName ( classname ) ) ); } // new -MH- // return list of fields for given class instance public static String getFields ( Object obj ) throws ClassNotFoundException { return ( getFields ( obj.getClass () ) ); } public static Method findMethod ( Class cls, String name, Class[] argTypes ) { try { return cls.getMethod ( name, argTypes ); } catch ( Exception e ) { Method[] mList = cls.getMethods (); Method m; for ( int i = 0; i < mList.length; i++ ) { m = mList[i]; if ( m.getName ().equals ( name ) && m.getParameterTypes ().length == argTypes.length && isCallableFrom ( m, argTypes ) ) { return m; } } return null; } } public static Constructor findConstructor ( Class cls, Class[] argTypes ) { try { return cls.getConstructor ( argTypes ); } catch ( Exception e ) { Constructor[] cList = cls.getConstructors (); //System.out.println("# constructors: " + cList.length); Constructor c; for ( int i = 0; i < cList.length; i++ ) { //System.out.println("Considering constructor: " + cList[i]); c = cList[i]; if ( c.getParameterTypes ().length == argTypes.length && isCallableFrom ( c, argTypes ) ) { return c; } } return null; } } private static Object invokeMethod ( Method m, Object target, Object[] args ) throws Exception { try { return m.invoke ( target, args ); } catch ( IllegalAccessException ex ) { String mName = m.getName (); Class[] pTypes = m.getParameterTypes (); Class currClass = target.getClass (); while ( currClass != null ) { try { Method meth = currClass.getMethod ( mName, pTypes ); if ( !meth.equals ( m ) ) { return meth.invoke ( target, args ); } } catch ( NoSuchMethodException ex2 ) {} catch ( IllegalAccessException ex2 ) {} Class[] ifaceList = currClass.getInterfaces (); for ( int i = 0; i < ifaceList.length; i++ ) { try { Method meth = ifaceList[i].getMethod ( mName, pTypes ); return meth.invoke ( target, args ); } catch ( NoSuchMethodException ex2 ) {} catch ( IllegalAccessException ex2 ) {} } currClass = currClass.getSuperclass (); } throw ex; } } public static Object invokeMethod ( Object target, String name, Object[] args, Class[] argTypes ) throws Throwable { Method m = findMethod ( target.getClass (), name, argTypes ); if ( m != null ) { try { Object result = invokeMethod ( m, target, castArguments ( args, argTypes, m.getParameterTypes () ) ); return result; } catch ( InvocationTargetException ex ) { throw ex.getCause (); } } else { throw new NoSuchMethodException ( name ); } } public static Object invokeStaticMethod ( String cls, String name, Object[] args, Class[] argTypes ) throws Throwable { Method m = findMethod ( Class.forName ( cls, true, loader ), name, argTypes ); if ( m != null ) { try { Object result = m.invoke ( null, castArguments ( args, argTypes, m.getParameterTypes () ) ); return result; } catch ( InvocationTargetException ex ) { throw ex.getCause (); } } else { throw new NoSuchMethodException ( name ); } } public static Object invokeConstructor ( String cls, Object[] args, Class[] argTypes ) throws Throwable { Constructor c = findConstructor ( Class.forName ( cls, true, loader ), argTypes ); if ( c != null ) { try { Object result = c.newInstance ( castArguments ( args, argTypes, c.getParameterTypes () ) ); return result; } catch ( InvocationTargetException ex ) { throw ex.getCause (); } } else { throw new NoSuchMethodException ( cls ); } } public static Object getField ( Object target, String name ) throws Throwable { try { Field f = target.getClass ().getField ( name ); return f.get ( target ); } catch ( NoSuchFieldException ex ) { try { return invokeMethod ( target, name, new Object[0], new Class[0] ); } catch ( NoSuchMethodException ex2 ) { throw ex; } } } public static Object getStaticField ( String cls, String name ) throws Throwable { try { Field f = Class.forName ( cls, true, loader ).getField ( name ); return f.get ( null ); } catch ( NoSuchFieldException ex ) { try { return invokeStaticMethod ( cls, name, new Object[0], new Class[0] ); } catch ( NoSuchMethodException ex2 ) { throw ex; } } } public static void setField ( Object target, String name, Object value ) throws Exception { Field f = target.getClass ().getField ( name ); f.set ( target, castArgument ( value, value.getClass (), f.getType () ) ); } public static void setStaticField ( String cls, String name, Object value ) throws Exception { Field f = Class.forName ( cls, true, loader ).getField ( name ); f.set ( null, castArgument ( value, value.getClass (), f.getType () ) ); } private static boolean isCallableFrom ( Method m, Class[] argTypes ) { Class[] expTypes = m.getParameterTypes (); for ( int i = 0; i < argTypes.length; i++ ) { if ( !isCallableFrom ( expTypes[i], argTypes[i] ) ) { return false; } } return true; } private static boolean isCallableFrom ( Constructor c, Class[] argTypes ) { Class[] expTypes = c.getParameterTypes (); for ( int i = 0; i < argTypes.length; i++ ) { if ( !isCallableFrom ( expTypes[i], argTypes[i] ) ) { return false; } } return true; } private static boolean isCallableFrom ( Class expCls, Class argCls ) { //System.out.println("isCallableFrom: "+expCls.getCanonicalName() + " <=? " + argCls.getCanonicalName()); if ( argCls == null ) { return!expCls.isPrimitive (); } else if ( expCls.isAssignableFrom ( argCls ) ) { return true; } else if ( ( isNumberClass ( expCls ) || isBooleanClass ( expCls ) ) && isNumberClass ( argCls ) ) { return true; } else if ( isCharClass ( expCls ) && argCls.equals ( Character.class ) ) { /* modified into a more strict check to avoid char to string matching to avoid matching method signatureslike java_method(char) with octave_call('a String') Date: 28-08-2010 Author: Martin Hepperle */ return true; } else if ( isStringClass ( expCls ) && argCls.equals ( String.class ) ) { /* added for strict String to String matching java_method(String) with octave_call('a String') but not java_method(char) with octave_call('a String') Date: 28-08-2010 Author: Martin Hepperle */ return true; } else if ( expCls.isArray () && argCls.isArray () && isCallableFrom ( expCls.getComponentType (), argCls.getComponentType () ) ) { return true; } else if ( expCls.equals ( Object.class ) && argCls.isPrimitive () ) { return true; } else { return false; } } private static boolean isNumberClass ( Class cls ) { return ( cls.equals ( Integer.TYPE ) || cls.equals ( Integer.class ) || cls.equals ( Short.TYPE ) || cls.equals ( Short.class ) || cls.equals ( Long.TYPE ) || cls.equals ( Long.class ) || cls.equals ( Float.TYPE ) || cls.equals ( Float.class ) || cls.equals ( Double.TYPE ) || cls.equals ( Double.class ) ); } private static boolean isBooleanClass ( Class cls ) { return ( cls.equals ( Boolean.class ) || cls.equals ( Boolean.TYPE ) ); } private static boolean isCharClass ( Class cls ) { return ( cls.equals ( Character.class ) || cls.equals ( Character.TYPE ) ); } /** * Check whether the supplied class is a String class. * * Added for more strict char/string mathicng of method signatures * Date: 28-08-2010 * Author: Martin Hepperle * @param cls Class - the class to check * @return boolean - true if clas is of class java.lang.String */ private static boolean isStringClass ( Class cls ) { return ( cls.equals ( String.class ) ); } private static Object[] castArguments ( Object[] args, Class[] argTypes, Class[] expTypes ) { for ( int i = 0; i < args.length; i++ ) { args[i] = castArgument ( args[i], argTypes[i], expTypes[i] ); } return args; } private static Object castArgument ( Object obj, Class type, Class expType ) { // System.out.println("expType:"+expType.getCanonicalName() + " <= type:" + type.getCanonicalName()); if ( type == null || expType.isAssignableFrom ( type ) ) { return obj; } else if ( isNumberClass ( expType ) ) { if ( expType.equals ( Integer.TYPE ) || expType.equals ( Integer.class ) ) { return new Integer ( ( ( Number ) obj ).intValue () ); } else if ( expType.equals ( Double.TYPE ) || expType.equals ( Double.class ) ) { return new Double ( ( ( Number ) obj ).doubleValue () ); } else if ( expType.equals ( Short.TYPE ) || expType.equals ( Short.class ) ) { return new Short ( ( ( Number ) obj ).shortValue () ); } else if ( expType.equals ( Long.TYPE ) || expType.equals ( Long.class ) ) { return new Long ( ( ( Number ) obj ).longValue () ); } } else if ( isBooleanClass ( expType ) ) { return new Boolean ( ( ( Number ) obj ).intValue () != 0 ); } else if ( isCharClass ( expType ) ) { String s = obj.toString (); if ( s.length () != 1 ) { throw new ClassCastException ( "cannot cast " + s + " to character" ); } return new Character ( s.charAt ( 0 ) ); } else if ( expType.isArray () && type.isArray () ) { return castArray ( obj, type.getComponentType (), expType.getComponentType () ); } else if ( type.isPrimitive () ) { return obj; } return null; } private static Object castArray ( Object obj, Class elemType, Class elemExpType ) { int len = Array.getLength ( obj ); Object result = Array.newInstance ( elemExpType, len ); for ( int i = 0; i < len; i++ ) { Array.set ( result, i, castArgument ( Array.get ( obj, i ), elemType, elemExpType ) ); } return result; } private static int getArrayClassNDims ( Class cls ) { if ( cls != null && cls.isArray () ) { return ( 1 + getArrayClassNDims ( cls.getComponentType () ) ); } else { return 0; } } private static Class getArrayElemClass ( Class cls ) { if ( cls.isArray () ) { return getArrayElemClass ( cls.getComponentType () ); } else { return cls; } } private static Object getArrayElements ( Object array, int[][] idx, int offset, int ndims, Class elemType ) { if ( offset >= ndims ) { Object elem = Array.get ( array, idx[offset][0] ); if ( offset < idx.length - 1 ) { return getArrayElements ( elem, idx, offset + 1, ndims, elemType ); } else { return elem; } } else { Class compType = elemType.getComponentType (); Object retval = Array.newInstance ( compType, idx[offset].length ); for ( int i = 0; i < idx[offset].length; i++ ) { Object elem = Array.get ( array, idx[offset][i] ); if ( offset < idx.length - 1 ) { elem = getArrayElements ( elem, idx, offset + 1, ndims, compType ); } Array.set ( retval, i, elem ); } return retval; } } public static Object arraySubsref ( Object obj, int[][] idx ) throws Exception { if ( !obj.getClass ().isArray () ) { throw new IllegalArgumentException ( "not a Java array" ); } if ( idx.length == 1 ) { if ( idx[0].length == 1 ) { return Array.get ( obj, idx[0][0] ); } else { Object retval = Array.newInstance ( obj.getClass (). getComponentType (), idx[0].length ); for ( int i = 0; i < idx[0].length; i++ ) { Array.set ( retval, i, Array.get ( obj, idx[0][i] ) ); } return retval; } } else { int[] dims = new int[idx.length]; for ( int i = 0; i < idx.length; i++ ) { dims[i] = idx[i].length; } if ( dims.length != getArrayClassNDims ( obj.getClass () ) ) { throw new IllegalArgumentException ( "index size mismatch" ); } /* resolve leading singletons */ Object theObj = obj; int offset = 0; while ( dims[offset] == 1 ) { theObj = Array.get ( theObj, idx[offset][0] ); offset = offset + 1; if ( offset >= dims.length ) { return theObj; } } if ( offset > 0 ) { int[][] new_idx = new int[idx.length - offset][]; System.arraycopy ( idx, offset, new_idx, 0, idx.length - offset ); return arraySubsref ( theObj, new_idx ); } /* chop trailing singletons */ int ndims = dims.length; while ( ndims > 1 && dims[ndims - 1] == 1 ) { ndims--; } /* create result array */ Class elemClass = theObj.getClass (); for ( int i = 0; i <= ( dims.length - ndims ); i++ ) { elemClass = elemClass.getComponentType (); } Object retval = Array.newInstance ( elemClass, dims[0] ); /* fill-in array */ for ( int i = 0; i < idx[0].length; i++ ) { Object elem = getArrayElements ( Array.get ( theObj, idx[0][i] ), idx, 1, ndims, elemClass ); Array.set ( retval, i, elem ); } return retval; } } private static Object setArrayElements ( Object array, int[][] idx, int offset, int ndims, Object rhs ) throws Exception { if ( offset >= ndims ) { if ( offset < idx.length - 1 ) { setArrayElements ( Array.get ( array, idx[offset][0] ), idx, offset + 1, ndims, rhs ); } else { Array.set ( array, idx[offset][0], rhs ); } return array; } else { for ( int i = 0; i < idx[offset].length; i++ ) { if ( offset < idx.length - 1 ) { setArrayElements ( Array.get ( array, idx[offset][i] ), idx, offset + 1, ndims, Array.get ( rhs, i ) ); } else { Array.set ( array, idx[offset][i], Array.get ( rhs, i ) ); } } return array; } } public static Object arraySubsasgn ( Object obj, int[][] idx, Object rhs ) throws Exception { if ( !obj.getClass ().isArray () ) { throw new IllegalArgumentException ( "not a Java array" ); } if ( idx.length == 1 ) { if ( idx[0].length == 1 ) { Array.set ( obj, idx[0][0], rhs ); } else { for ( int i = 0; i < idx[0].length; i++ ) { Array.set ( obj, idx[0][i], Array.get ( rhs, i ) ); } } return obj; } else { int[] dims = new int[idx.length]; for ( int i = 0; i < idx.length; i++ ) { dims[i] = idx[i].length; } if ( dims.length != getArrayClassNDims ( obj.getClass () ) ) { throw new IllegalArgumentException ( "index size mismatch" ); } /* resolve leading singletons */ Object theObj = obj; int offset = 0; while ( dims[offset] == 1 && offset < ( dims.length - 1 ) ) { theObj = Array.get ( theObj, idx[offset][0] ); offset = offset + 1; } if ( offset > 0 ) { int[][] new_idx = new int[idx.length - offset][]; System.arraycopy ( idx, offset, new_idx, 0, idx.length - offset ); arraySubsasgn ( theObj, new_idx, rhs ); return obj; } /* chop trailing singletons */ int ndims = dims.length; while ( ndims > 1 && dims[ndims - 1] == 1 ) { ndims--; } for ( int i = 0; i < idx[0].length; i++ ) { setArrayElements ( Array.get ( theObj, idx[0][i] ), idx, 1, ndims, Array.get ( rhs, i ) ); } return obj; } } public static Object createArray ( Object cls, int[] dims ) throws Exception { Class theClass; if ( cls instanceof Class ) { theClass = ( Class ) cls; } else if ( cls instanceof String ) { theClass = Class.forName ( ( String ) cls, true, loader ); } else { throw new IllegalArgumentException ( "invalid class specification " + cls ); } return Array.newInstance ( theClass, dims ); } public static Object createArray ( Object cls, int length ) throws Exception { return createArray ( cls, new int[] {length} ); } }