/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sam Ruby (rubys@us.ibm.com) | +----------------------------------------------------------------------+ */ /* $Id$ */ package net.php; import java.lang.reflect.*; import java.util.*; import java.beans.*; public class reflect { static { loadLibrary("reflect"); } protected static void loadLibrary(String property) { try { ResourceBundle bundle = ResourceBundle.getBundle("net.php."+property); System.loadLibrary(bundle.getString("library")); } catch (Exception e) { e.printStackTrace(); } } // // Native methods // private static native void setResultFromString(long result, byte value[]); private static native void setResultFromLong(long result, long value); private static native void setResultFromDouble(long result, double value); private static native void setResultFromBoolean(long result, boolean value); private static native void setResultFromObject(long result, Object value); private static native void setResultFromArray(long result); private static native long nextElement(long array); private static native long hashUpdate(long array, byte key[]); private static native long hashIndexUpdate(long array, long key); private static native void setException(long result, byte value[]); public static native void setEnv(); // // Helper routines which encapsulate the native methods // public static void setResult(long result, Object value) { if (value == null) return; if (value instanceof java.lang.String) { setResultFromString(result, ((String)value).getBytes()); } else if (value instanceof java.lang.Number) { if (value instanceof java.lang.Integer || value instanceof java.lang.Short || value instanceof java.lang.Byte) { setResultFromLong(result, ((Number)value).longValue()); } else { /* Float, Double, BigDecimal, BigInteger, Double, Long, ... */ setResultFromDouble(result, ((Number)value).doubleValue()); } } else if (value instanceof java.lang.Boolean) { setResultFromBoolean(result, ((Boolean)value).booleanValue()); } else if (value.getClass().isArray()) { long length = Array.getLength(value); setResultFromArray(result); for (int i=0; i 0) { throw new InstantiationException("No matching constructor found"); } else { // for classes which have no visible constructor, return the class // useful for classes like java.lang.System and java.util.Calendar. setResult(result, Class.forName(name)); return; } } Object coercedArgs[] = coerce(selected.getParameterTypes(), args); setResultFromObject(result, selected.newInstance(coercedArgs)); } catch (Exception e) { setException(result, e); } } // // Select the best match from a list of methods // private static Object select(Vector methods, Object args[]) { if (methods.size() == 1) return methods.firstElement(); Object selected = null; int best = Integer.MAX_VALUE; for (Enumeration e = methods.elements(); e.hasMoreElements(); ) { Object element = e.nextElement(); int weight=0; Class parms[] = (element instanceof Method) ? ((Method)element).getParameterTypes() : ((Constructor)element).getParameterTypes(); for (int i=0; i0) weight+=((String)args[i]).length(); else weight+=9999; } else { weight+=9999; } } else { weight+=9999; } } if (weight < best) { if (weight == 0) return element; best = weight; selected = element; } } return selected; } // // Coerce arguments when possible to conform to the argument list. // Java's reflection will automatically do widening conversions, // unfortunately PHP only supports wide formats, so to be practical // some (possibly lossy) conversions are required. // private static Object[] coerce(Class parms[], Object args[]) { Object result[] = args; for (int i=0; i= size) size = index+1; } Object tempArray[] = new Object[size]; Class tempTarget[] = new Class[size]; Class targetType = parms[i].getComponentType(); // flatten the hash table into an array for (int j=0; j0;) { if (Modifier.isPublic(interfaces[i].getModifiers())) { jclass=interfaces[i]; } } } Method methods[] = jclass.getMethods(); for (int i=0; i0;) { if (Modifier.isPublic(interfaces[i].getModifiers())) { jclass=interfaces[i]; } } } BeanInfo beanInfo = Introspector.getBeanInfo(jclass); PropertyDescriptor props[] = beanInfo.getPropertyDescriptors(); for (int i=0; i0) { method=props[i].getWriteMethod(); args = coerce(method.getParameterTypes(), args); } else { method=props[i].getReadMethod(); } setResult(result, method.invoke(object, args)); return; } } Field jfields[] = jclass.getFields(); for (int i=0; i0) { args = coerce(new Class[] {jfields[i].getType()}, args); jfields[i].set(object, args[0]); } else { setResult(result, jfields[i].get(object)); } return; } } // try a second time with the object itself, if it is of type Class if (!(object instanceof Class) || (jclass==object)) break; } } catch (Exception e) { setException(result, e); } } // // Helper routines for the C implementation // public Object MakeArg(boolean b) { return new Boolean(b); } public Object MakeArg(long l) { return new Long(l); } public Object MakeArg(double d) { return new Double(d); } }