diff options
Diffstat (limited to 'plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MethodHelper.java')
-rw-r--r-- | plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MethodHelper.java | 272 |
1 files changed, 0 insertions, 272 deletions
diff --git a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MethodHelper.java b/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MethodHelper.java deleted file mode 100644 index 3bceb66e4..000000000 --- a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MethodHelper.java +++ /dev/null @@ -1,272 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2006 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jem.internal.proxy.common; -import java.lang.reflect.*; -import java.text.MessageFormat; -import java.util.*; - -/** - * This is a class to do message/constructor work. - * Specifically to find the most appropriate method. - */ -public class MethodHelper { - - /* - * The class that is used to represent Null class type. - * - * @since 1.0.0 - */ - private static class NULL_CLASS { - } - - public static final Class NULL_TYPE = NULL_CLASS.class; - - static final ArrayList sPrimitivesOrder; - static final int sCharPos; - - static { - sPrimitivesOrder = new ArrayList(6); - sPrimitivesOrder.add(Byte.TYPE); - sPrimitivesOrder.add(Short.TYPE); - sPrimitivesOrder.add(Integer.TYPE); - sPrimitivesOrder.add(Long.TYPE); - sPrimitivesOrder.add(Float.TYPE); - sPrimitivesOrder.add(Double.TYPE); - - // char can be treated like a short for purposes of ordering. - sCharPos = sPrimitivesOrder.indexOf(Short.TYPE); - } - - /** - * Return whether the type2 can be assigned to type1 in - * method argument conversion. - */ - public static boolean isAssignableFrom(Class type1, Class type2) { - if (type1 == type2) - return true; // They're the same, so assignable. - if (type1.isPrimitive()) { - if (type2.isPrimitive()) { - if (type1 == Boolean.TYPE || type2 == Boolean.TYPE) - return false; // Since not equal and one is boolean and the other isn't, not assignable - int type1Pos = (type1 != Character.TYPE) ? sPrimitivesOrder.indexOf(type1) : sCharPos; - int type2Pos = (type2 != Character.TYPE) ? sPrimitivesOrder.indexOf(type2) : sCharPos; - return type1Pos > type2Pos; // It can be widened if type1 is higher in the order - } - return false; // primitive to non-primitive, not assignable. - } else - if (type2 == NULL_TYPE) - return true; // NULL_TYPE represents null for us, and null can be assigned to any object - else - return type1.isAssignableFrom(type2); // Can type2 be assigned to type1 - } - - - /** - * Every entry in Array2 can be assigned to the corresponding entry in Array1. - */ - public static boolean isAssignableFrom(Class[] types1, Class[] types2) { - if (types1.length != types2.length) - return false; // Not the same size, so not compatible. - for (int i=0; i<types1.length; i++) { - if (!isAssignableFrom(types1[i], types2[i])) - return false; - } - return true; // All are assignable - } - - /** - * Return the index of the most compatible method/constructor from the lists passed in. - * MethodsList: List of methods (if null then this is for constructors) - * ParmsList: List of parms for each method (each entry will be Class[]). - */ - private static int findMostCompatible(List methods, List parms, String ambiguousName) throws AmbiguousMethodException { - // The algorithm used is from the Java Language Specification 15.12.2.2 - // Find the maximally specific ones - // This is defined as the one that is more specific then all of the rest. - // If there are duplicates parms that are maximally specific, then it doesn't matter which choosen - // because when invoked the JVM will make sure the right thing is done. - // - Class[][] parmsCopy = (Class[][]) parms.toArray(new Class[parms.size()][]); - int size = parmsCopy.length; - // For each entry see if it is maximally specific, i.e. it is more specific then all of the others. -nextMethod: for (int i=0; i<size; i++) { - // For ctors we don't need to test the declaring class because it will always be the same class. - Class dclClassi = methods != null ? ((Method) methods.get(i)).getDeclaringClass() : null; - Class[] parmsi = parmsCopy[i]; - for (int j=0; j<size; j++) { - if (i == j) - continue; - // Methodi is more specific if - // a) Methodi declaring class is assignable to Methodj declaring class - // b) Methodi parms are assignable to Methodj parms - // - // First see if Methodi is more specific, if it is - // then throw out Methodj and continue - // If Methodi is not compatible to Methodj, go to the next method for i. Methodi is not the most specific - // Something else is either more specific or none are ma - if (dclClassi != null) { - // Step a - if (!isAssignableFrom(((Method) methods.get(j)).getDeclaringClass(), dclClassi)) - continue nextMethod; // Methodi is not more specific than Methodj, so try next i. - } - - // Step b - Class[] parmsj = parmsCopy[j]; - if (!isAssignableFrom(parmsj, parmsi)) { - // Methodi is not more specific than Methodj, so go to next i. - continue nextMethod; - } - } - return i; // Methodi is more specific than all of the other ones. - } - - throw new AmbiguousMethodException(ambiguousName); // There was not one more specific than all of the others. - } - - /** - * Find the most compatible method for the given arguments. - */ - public static Method findCompatibleMethod(Class receiver, String methodName, Class[] arguments) throws NoSuchMethodException, AmbiguousMethodException { - try { - return receiver.getMethod(methodName, arguments); // Found exact match in public - } catch (NoSuchMethodException exc) { - if (arguments != null) { - // Need to find most compatible one. We will take protected into consideration (i.e. inheritance). - ArrayList parmsList = new ArrayList(); // The parm list from each compatible method. - ArrayList mthdsList = new ArrayList(); // The list of compatible methods, same order as the parms above. - Class cls = receiver; - while (cls != null) { - Method mthds[] = cls.getDeclaredMethods(); - for (int i = 0; i < mthds.length; i++) { - Method mthd = mthds[i]; - if (!mthd.getName().equals(methodName)) - continue; // Not compatible, not same name - int modifiers = mthd.getModifiers(); - if (!(Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers))) - continue; // Will not call private or package-protected because we don't know the context. - Class[] parms = mthd.getParameterTypes(); - // If exact match we found a non-public exact match, which is good. - if (Arrays.equals(arguments, parms)) - return makeMethodAccessable(mthd); - if (!isAssignableFrom(parms, arguments)) - continue; // Not compatible, parms - // It is compatible with the requested method - now see if we already have an exact match from a subclass. Don't want to add it twice. - // We are assuming the actual number of compatible methods is small, so this O(n-squared) search is efficient enough. - int size = parmsList.size(); - for (int j = 0; j < size; j++) { - if (Arrays.equals(parms, (Object[]) parmsList.get(j))) - continue; - } - parmsList.add(parms); - mthdsList.add(mthd); - } - cls = cls.getSuperclass(); - } - // Now have list of compatible methods. - if (parmsList.size() == 0) - throw throwFixedNoSuchMethod(exc, receiver, methodName, arguments); // None found, so rethrow the exception - if (parmsList.size() == 1) - return makeMethodAccessable((Method) mthdsList.get(0)); // Only one, so return it - - // Now find the most compatible method - int mostCompatible = findMostCompatible(mthdsList, parmsList, methodName); - return makeMethodAccessable((Method) mthdsList.get(mostCompatible)); - } else - throw throwFixedNoSuchMethod(exc, receiver, methodName, arguments); // None found, so rethrow the exception - } - } - - private static Method makeMethodAccessable(Method m) { - m.setAccessible(true); // We allow all access, let ide and compiler handle security. - return m; - } - - /* - * NoSuchMEthodExeception doesn't include the signature. Since these are dynamic searches, the exception itself is useless without - * the signature. So we add it. - */ - private static NoSuchMethodException throwFixedNoSuchMethod(NoSuchMethodException e, Class declareClass, String methodName, Class[] argClasses) { - - // The default trace doesn't show what method was being searched for, so recreate with that. - StringBuffer s = new StringBuffer(); - s.append(declareClass.getName()); - s.append('.'); - s.append(methodName); - s.append('('); - if (argClasses != null) { - for (int i = 0; i < argClasses.length; i++) { - if (i > 0) - s.append(','); - s.append(argClasses[i].getName()); - } - } - s.append(')'); - NoSuchMethodException ne = new NoSuchMethodException(s.toString()); - ne.setStackTrace(e.getStackTrace()); - return ne; - } - - - /** - * Find the most compatible constructor for the class with the given arguments. - * @param receiver class to get the constructor for - * @param arguments array of argument types - * @return the constructor - * @throws NoSuchMethodException no compatible constructor can be found - * @throws AmbiguousMethodException there is more than one compatible constructor - * @throws IllegalAccessException it can't be accessed. Such as it is a non-static inner class. - * - * @since 1.2.0 - */ - public static Constructor findCompatibleConstructor(Class receiver, Class[] arguments) throws NoSuchMethodException, AmbiguousMethodException, IllegalAccessException { - if (receiver.getDeclaringClass() != null && !Modifier.isStatic(receiver.getModifiers())) - throw new IllegalAccessException(MessageFormat.format(Messages.getString("MethodHelper.NONSTATICINNERCLASS_WARNING"), new Object[] {receiver.getName()})); //$NON-NLS-1$ - try { - java.lang.reflect.Constructor ctor = receiver.getDeclaredConstructor(arguments); - ctor.setAccessible(true); // We allow all access, let ide and compiler handle security. - return ctor; // Found exact match - } catch (NoSuchMethodException exc) { - if (arguments != null) { - // Need to find most compatible one. - java.lang.reflect.Constructor ctors[] = receiver.getDeclaredConstructors(); - ArrayList parmsList = new ArrayList(ctors.length); // The parm list from each compatible method. - ArrayList ctorsList = new ArrayList(ctors.length); // The list of compatible methods, same order as the parms above. - for (int i = 0; i < ctors.length; i++) { - java.lang.reflect.Constructor ctor = ctors[i]; - Class[] parms = ctor.getParameterTypes(); - if (!isAssignableFrom(parms, arguments)) - continue; // Not compatible, parms - // It is compatible with the requested method - parmsList.add(parms); - ctorsList.add(ctor); - } - - // Now have list of compatible methods. - if (parmsList.size() == 0) - throw exc; // None found, so rethrow the exception - if (parmsList.size() == 1) { - java.lang.reflect.Constructor ctor = (java.lang.reflect.Constructor) ctorsList.get(0); // Only one, so return it - ctor.setAccessible(true); // We allow all access, let ide and compilor handle security. - return ctor; - } - - // Now find the most compatible ctor - int mostCompatible = findMostCompatible(null, parmsList, receiver.getName()); - java.lang.reflect.Constructor ctor = (java.lang.reflect.Constructor) ctorsList.get(mostCompatible); - ctor.setAccessible(true); // We allow all access, let ide and compilor handle security. - return ctor; - } else - throw exc; // None found, so rethrow the exception - } - } - - -} |