methodresolver.java
来自「java jdk 1.4的源码」· Java 代码 · 共 1,035 行 · 第 1/3 页
JAVA
1,035 行
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, Lotus * Development Corporation., http://www.lotus.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package org.apache.xalan.extensions;import java.lang.reflect.Method;import java.lang.reflect.Constructor;import java.lang.reflect.Modifier;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.w3c.dom.traversal.NodeIterator;import org.apache.xpath.objects.XObject;import org.apache.xpath.objects.XString;import org.apache.xpath.objects.XRTreeFrag;import org.apache.xml.dtm.*;import org.apache.xml.dtm.ref.DTMNodeIterator;import org.apache.xml.dtm.ref.DTMNodeList;import org.apache.xml.dtm.ref.DTMNodeProxy;import org.apache.xalan.res.XSLMessages;import org.apache.xalan.res.XSLTErrorResources;import javax.xml.transform.TransformerException;/** * Utility class to help resolve method overloading with Xalan XSLT * argument types. */public class MethodResolver{ /** * Specifies a search for static methods only. */ public static final int STATIC_ONLY = 1; /** * Specifies a search for instance methods only. */ public static final int INSTANCE_ONLY = 2; /** * Specifies a search for both static and instance methods. */ public static final int STATIC_AND_INSTANCE = 3; /** * Specifies a Dynamic method search. If the method being * evaluated is a static method, all arguments are used. * Otherwise, it is an instance method and only arguments * beginning with the second argument are used. */ public static final int DYNAMIC = 4; /** * Given a class, figure out the resolution of * the Java Constructor from the XSLT argument types, and perform the * conversion of the arguments. * @param classObj the Class of the object to be constructed. * @param argsIn An array of XSLT/XPath arguments. * @param argsOut An array of the exact size as argsIn, which will be * populated with converted arguments if a suitable method is found. * @return A constructor that will work with the argsOut array. * @throws TransformerException may be thrown for Xalan conversion * exceptions. */ public static Constructor getConstructor(Class classObj, Object[] argsIn, Object[][] argsOut, ExpressionContext exprContext) throws NoSuchMethodException, SecurityException, TransformerException { Constructor bestConstructor = null; Class[] bestParamTypes = null; Constructor[] constructors = classObj.getConstructors(); int nMethods = constructors.length; int bestScore = Integer.MAX_VALUE; int bestScoreCount = 0; for(int i = 0; i < nMethods; i++) { Constructor ctor = constructors[i]; Class[] paramTypes = ctor.getParameterTypes(); int numberMethodParams = paramTypes.length; int paramStart = 0; boolean isFirstExpressionContext = false; int scoreStart; // System.out.println("numberMethodParams: "+numberMethodParams); // System.out.println("argsIn.length: "+argsIn.length); // System.out.println("exprContext: "+exprContext); if(numberMethodParams == (argsIn.length+1)) { Class javaClass = paramTypes[0]; // System.out.println("first javaClass: "+javaClass.getName()); if(ExpressionContext.class.isAssignableFrom(javaClass)) { isFirstExpressionContext = true; scoreStart = 0; paramStart++; // System.out.println("Incrementing paramStart: "+paramStart); } else continue; } else scoreStart = 1000; if(argsIn.length == (numberMethodParams - paramStart)) { // then we have our candidate. int score = scoreMatch(paramTypes, paramStart, argsIn, scoreStart); // System.out.println("score: "+score); if(-1 == score) continue; if(score < bestScore) { // System.out.println("Assigning best ctor: "+ctor); bestConstructor = ctor; bestParamTypes = paramTypes; bestScore = score; bestScoreCount = 1; } else if (score == bestScore) bestScoreCount++; } } if(null == bestConstructor) { throw new NoSuchMethodException(errString("function", "constructor", classObj, "", 0, argsIn)); } /*** This is commented out until we can do a better object -> object scoring else if (bestScoreCount > 1) throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_MORE_MATCH_CONSTRUCTOR, new Object[]{classObj.getName()})); //"More than one best match for constructor for " + classObj.getName()); ***/ else convertParams(argsIn, argsOut, bestParamTypes, exprContext); return bestConstructor; } /** * Given the name of a method, figure out the resolution of * the Java Method from the XSLT argument types, and perform the * conversion of the arguments. * @param classObj The Class of the object that should have the method. * @param name The name of the method to be invoked. * @param argsIn An array of XSLT/XPath arguments. * @param argsOut An array of the exact size as argsIn, which will be * populated with converted arguments if a suitable method is found. * @return A method that will work with the argsOut array. * @throws TransformerException may be thrown for Xalan conversion * exceptions. */ public static Method getMethod(Class classObj, String name, Object[] argsIn, Object[][] argsOut, ExpressionContext exprContext, int searchMethod) throws NoSuchMethodException, SecurityException, TransformerException { // System.out.println("---> Looking for method: "+name); // System.out.println("---> classObj: "+classObj); if (name.indexOf("-")>0) name = replaceDash(name); Method bestMethod = null; Class[] bestParamTypes = null; Method[] methods = classObj.getMethods(); int nMethods = methods.length; int bestScore = Integer.MAX_VALUE; int bestScoreCount = 0; boolean isStatic; for(int i = 0; i < nMethods; i++) { Method method = methods[i]; // System.out.println("looking at method: "+method); int xsltParamStart = 0; if(method.getName().equals(name)) { isStatic = Modifier.isStatic(method.getModifiers()); switch(searchMethod) { case STATIC_ONLY: if (!isStatic) { continue; } break; case INSTANCE_ONLY: if (isStatic) { continue; } break; case STATIC_AND_INSTANCE: break; case DYNAMIC: if (!isStatic) xsltParamStart = 1; } int javaParamStart = 0; Class[] paramTypes = method.getParameterTypes(); int numberMethodParams = paramTypes.length; boolean isFirstExpressionContext = false; int scoreStart; // System.out.println("numberMethodParams: "+numberMethodParams); // System.out.println("argsIn.length: "+argsIn.length); // System.out.println("exprContext: "+exprContext); int argsLen = (null != argsIn) ? argsIn.length : 0; if(numberMethodParams == (argsLen-xsltParamStart+1)) { Class javaClass = paramTypes[0]; if(ExpressionContext.class.isAssignableFrom(javaClass)) { isFirstExpressionContext = true; scoreStart = 0; javaParamStart++; } else { continue; } } else scoreStart = 1000; if((argsLen - xsltParamStart) == (numberMethodParams - javaParamStart)) { // then we have our candidate. int score = scoreMatch(paramTypes, javaParamStart, argsIn, scoreStart); // System.out.println("score: "+score); if(-1 == score) continue; if(score < bestScore) { // System.out.println("Assigning best method: "+method); bestMethod = method; bestParamTypes = paramTypes; bestScore = score; bestScoreCount = 1; } else if (score == bestScore) bestScoreCount++; } } } if (null == bestMethod) { throw new NoSuchMethodException(errString("function", "method", classObj, name, searchMethod, argsIn)); } /*** This is commented out until we can do a better object -> object scoring else if (bestScoreCount > 1) throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_MORE_MATCH_METHOD, new Object[]{name})); //"More than one best match for method " + name); ***/ else convertParams(argsIn, argsOut, bestParamTypes, exprContext); return bestMethod; } /** * To support EXSLT extensions, convert names with dash to allowable Java names: * e.g., convert abc-xyz to abcXyz. * Note: dashes only appear in middle of an EXSLT function or element name. */ private static String replaceDash(String name) { char dash = '-'; StringBuffer buff = new StringBuffer(""); for (int i=0; i<name.length(); i++) { if (name.charAt(i) == dash) {} else if (i > 0 && name.charAt(i-1) == dash) buff.append(Character.toUpperCase(name.charAt(i))); else buff.append(name.charAt(i));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?