[richfaces-svn-commits] JBoss Rich Faces SVN: r15931 - in tags: rf_363451/framework/impl/src/main/java/org/ajax4jsf/renderkit/compiler and 1 other directory.

richfaces-svn-commits at lists.jboss.org richfaces-svn-commits at lists.jboss.org
Thu Nov 19 14:15:29 EST 2009


Author: konstantin.mishin
Date: 2009-11-19 14:15:29 -0500 (Thu, 19 Nov 2009)
New Revision: 15931

Added:
   tags/rf_363451/
Modified:
   tags/rf_363451/framework/impl/src/main/java/org/ajax4jsf/renderkit/compiler/MethodCallElement.java
Log:
RFPL-252

Copied: tags/rf_363451 (from rev 15930, branches/enterprise/3.3.X)

Modified: tags/rf_363451/framework/impl/src/main/java/org/ajax4jsf/renderkit/compiler/MethodCallElement.java
===================================================================
--- branches/enterprise/3.3.X/framework/impl/src/main/java/org/ajax4jsf/renderkit/compiler/MethodCallElement.java	2009-11-19 16:13:11 UTC (rev 15930)
+++ tags/rf_363451/framework/impl/src/main/java/org/ajax4jsf/renderkit/compiler/MethodCallElement.java	2009-11-19 19:15:29 UTC (rev 15931)
@@ -31,73 +31,88 @@
 import java.util.Map;
 
 import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
 import javax.faces.el.MethodNotFoundException;
+import javax.faces.render.Renderer;
 
 import org.ajax4jsf.Messages;
+import org.ajax4jsf.renderkit.RendererBase;
+import org.ajax4jsf.renderkit.RendererUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.xml.sax.SAXException;
 
-
 /**
  * @author asmirnov at exadel.com (latest modification by $Author: alexsmirnov $)
  * @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:57:47 $
- *
+ * 
  */
-public  class MethodCallElement extends ElementBase {
+public class MethodCallElement extends ElementBase {
 
 	public static final String UTILS_PREFIX = "utils.";
-	
+
 	static final Log _log = LogFactory.getLog(MethodCallElement.class);
 
 	private String _name = null;
-	
-	private List parameters = new ArrayList();
-	
-	private Invoker invoker = new Invoker();
-	
-	private MethodCacheState state = new MethodCacheState();
-	
-	
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.renderkit.compiler.CompiledXML#encode(javax.faces.render.Renderer, javax.faces.context.FacesContext, javax.faces.component.UIComponent)
+
+	private List<MethodParameterElement> parameters = new ArrayList<MethodParameterElement>(
+			3);
+
+	private volatile Invoker invoker;
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.ajax4jsf.renderkit.compiler.CompiledXML#encode(javax.faces.render
+	 * .Renderer, javax.faces.context.FacesContext,
+	 * javax.faces.component.UIComponent)
 	 */
-	public void encode(TemplateContext context ) throws IOException {
-			getValue(context);
+	public void encode(TemplateContext context) throws IOException {
+		getValue(context);
 	}
 
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.renderkit.compiler.ElementBase#encode(org.ajax4jsf.renderkit.compiler.TemplateContext, java.lang.String)
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.ajax4jsf.renderkit.compiler.ElementBase#encode(org.ajax4jsf.renderkit
+	 * .compiler.TemplateContext, java.lang.String)
 	 */
-	public void encode(TemplateContext context, String breakPoint) throws IOException {
+	public void encode(TemplateContext context, String breakPoint)
+			throws IOException {
 		// Text not contain breakpoints.
 		encode(context);
 	}
-	
-	
+
 	public Object getValue(TemplateContext context) throws FacesException {
+		if (null == invoker) {
+			throw new FacesException(Messages
+					.getMessage(Messages.RENDERER_METHOD_NOT_SET_ERROR));
+		}
 		// prepare method params. we attempt to call 3 signatures :
 		// a) name(FacesContext,UIComponent [, param0...])
 		// b) name(TempalateContext [,param0...])
 		// c) name([param0...])
-		state.init(parameters);
-		Object[] values = state.computeParameterValues(context);
-		
-		InvokeData data = null;
-		synchronized (state) {
-			state.update(context, values, invoker);
-			data = invoker.invokeMethod(context, state);
-		}
-		return invoker.invokeMethod(data);
+		Object[] values = computeParameterValues(context);
+
+		return invoker.invokeMethod(context, values);
 		// perform childrens.
 		// super.encode(renderer,context,component);
 	}
 
+	public Object[] computeParameterValues(TemplateContext context) {
+		Object[] ps = new Object[parameters.size()];
+		for (int i = 0; i < ps.length; i++) {
+			ps[i] = parameters.get(i).valueGetter.getValueOrDefault(context);
+		}
+		return ps;
+	}
 
-
-	public void addParameter(MethodParameterElement parameter){
+	public void addParameter(MethodParameterElement parameter) {
 		parameters.add(parameter);
 	}
+
 	/**
 	 * @return Returns the methodName.
 	 */
@@ -106,13 +121,14 @@
 	}
 
 	/**
-	 * @param methodName The methodName to set.
+	 * @param methodName
+	 *            The methodName to set.
 	 */
 	public void setName(String methodName) {
-		if(methodName.startsWith(UTILS_PREFIX)){
+		if (methodName.startsWith(UTILS_PREFIX)) {
 			this._name = methodName.substring(UTILS_PREFIX.length());
 			this.invoker = getRendererUtilsInvoker(_name);
-		} else if(methodName.indexOf('.') >= 0) {
+		} else if (methodName.indexOf('.') >= 0) {
 			this._name = methodName;
 			this.invoker = getStaticInvoker(_name);
 		} else {
@@ -121,385 +137,430 @@
 		}
 	}
 
-	static Map staticInvokers = new HashMap();
-	
-	public StaticInvoker getStaticInvoker(String methodName) {
-		StaticInvoker invoker = (StaticInvoker)staticInvokers.get(methodName);
-		if(invoker == null) {
-			invoker = new StaticInvoker(methodName);
-			staticInvokers.put(methodName, invoker);
-		}
-		return invoker;		
+	public Invoker getStaticInvoker(String methodName) {
+		StaticInvoker invoker = new StaticInvoker(methodName);
+		return invoker;
 	}
 
-	static Map rendererInvokers = new HashMap();
-	
-	public RendererInvoker getRendererInvoker(String methodName) {
-		RendererInvoker invoker = (RendererInvoker)rendererInvokers.get(methodName);
-		if(invoker == null) {
-			invoker = new RendererInvoker(false, methodName);
-			rendererInvokers.put(methodName, invoker);
-		}
+	public Invoker getRendererInvoker(String methodName) {
+		RendererInvoker invoker = new RendererInvoker(methodName);
 		return invoker;
 	}
-	
-	static Map utilsInvokers = new HashMap();
 
-	public RendererInvoker getRendererUtilsInvoker(String methodName) {
-		RendererInvoker invoker = (RendererInvoker)utilsInvokers.get(methodName);
-		if(invoker == null) {
-			invoker = new RendererInvoker(true, methodName);
-			utilsInvokers.put(methodName, invoker);
-		}
+	public Invoker getRendererUtilsInvoker(String methodName) {
+		RendererInvoker invoker = new RendererUtilsInvoker(methodName);
 		return invoker;
 	}
-	
+
 	public String getTag() {
-		return HtmlCompiler.NS_PREFIX+HtmlCompiler.CALL_TAG;
+		return HtmlCompiler.NS_PREFIX + HtmlCompiler.CALL_TAG;
 	}
 
-	
-	/* (non-Javadoc)
-	 * @see org.ajax4jsf.renderkit.compiler.ElementBase#setParent(org.ajax4jsf.renderkit.compiler.PreparedTemplate)
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.ajax4jsf.renderkit.compiler.ElementBase#setParent(org.ajax4jsf.renderkit
+	 * .compiler.PreparedTemplate)
 	 */
-	public void setParent(PreparedTemplate parent) throws SAXException {		
+	public void setParent(PreparedTemplate parent) throws SAXException {
 		super.setParent(parent);
-		if (getName()==null) {
-			throw new SAXException(Messages.getMessage(Messages.NO_NAME_ATTRIBUTE_ERROR, getTag()));
+		if (getName() == null) {
+			throw new SAXException(Messages.getMessage(
+					Messages.NO_NAME_ATTRIBUTE_ERROR, getTag()));
 		}
 	}
 
-	
-/* (non-Javadoc)
-	 * @see org.ajax4jsf.renderkit.compiler.ElementBase#getString(org.ajax4jsf.renderkit.compiler.TemplateContext)
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.ajax4jsf.renderkit.compiler.ElementBase#getString(org.ajax4jsf.renderkit
+	 * .compiler.TemplateContext)
 	 */
 	public String getString(TemplateContext context) throws FacesException {
 		Object result = getValue(context);
-		if (null == result || result.toString().length()==0) {
-				result = "";
+		if (null == result || result.toString().length() == 0) {
+			result = "";
 		}
 		return result.toString();
 	}
 
-	/* (non-Javadoc)
+	/*
+	 * (non-Javadoc)
+	 * 
 	 * @see org.ajax4jsf.renderkit.compiler.ElementBase#getAllowedClasses()
 	 */
-	protected Class[] getAllowedClasses() {
-		// TODO Auto-generated method stub
-		return new Class[]{
-				MethodParameterElement.class,
-				ResourceElement.class
-		};
+	@SuppressWarnings("unchecked")
+	protected Class<? extends ElementBase>[] getAllowedClasses() {
+		return new Class[] { MethodParameterElement.class,
+				ResourceElement.class };
 	}
 
 }
 
-class InvokeData {
-	TemplateContext context;
-	Method method;
-	Object object;
-	Object[] arguments;
-	InvokeData(TemplateContext context, Method method, Object object, Object[] arguments) {
-		this.context = context;
-		this.method = method;
-		this.object = object;
-		this.arguments = (Object[]) arguments.clone();
-	}
-}
+abstract class Invoker {
 
-class Invoker {
-	String methodName;
+	protected volatile Signature current;
 
-	InvokeData invokeMethod(TemplateContext context, MethodCacheState state) {
-		throw new FacesException(Messages.getMessage(Messages.RENDERER_METHOD_NOT_SET_ERROR));
+	protected String methodName;
+
+	public Invoker(String name) {
+		this.methodName = name;
 	}
 
-	void handleInvocationTargetException(TemplateContext context, InvocationTargetException e) {}
-	void handleIllegalAccessException(TemplateContext context, IllegalAccessException e) {}
-	void handleMethodNotFoundException(TemplateContext context) throws MethodNotFoundException {}
-
-	InvokeData invokeMethod(TemplateContext context, Map methods, Class cls, Object object, MethodCacheState state) {
-		Method method = provideMethod(methods, cls, object, state);
-		return new InvokeData(context, method, object, state.current.arguments);
-	}
-	
-	Object invokeMethod(InvokeData data) {
-		if(data.method != null) {
+	public Object invokeMethod(TemplateContext context, Object[] parameters) {
+		Object result = null;
+		Class<?>[] parameterTypes = new Class[parameters.length];
+		for (int i = 0; i < parameters.length; i++) {
+			Object parameter = parameters[i];
+			if (null != parameter) {
+				parameterTypes[i] = parameter.getClass();
+			}
+		}
+		// Use a copy to avoid synchronization.
+			Signature signature = current;
+			if (null == signature
+					|| !signature.isApplicable(context, getInvokedClass(context),
+							parameterTypes)) {
+				// Clalculate target signature
+				signature = provideMethod(context, parameterTypes);
+				current = signature;
+			}
 			try {
-				return data.method.invoke(data.object, data.arguments);
+				result = signature.invoke(context, getInvokedObject(context),
+						parameters);
+			} catch (IllegalArgumentException e) {
+				throw new FacesException(e);
+			} catch (IllegalAccessException e) {
+				handleIllegalAccessException(context, e);
 			} catch (InvocationTargetException e) {
-				handleInvocationTargetException(data.context, e);
-			} catch (IllegalAccessException e) {
-				handleIllegalAccessException(data.context, e);
+				handleInvocationTargetException(context, e);
 			}
-		}
-		handleMethodNotFoundException(data.context);
-		return null;
+		return result;
 	}
-	
-	public Class getInvokedClass(TemplateContext context) {
-		return null;
-	}
-	
-	private Method provideMethod(Map methods, Class cls, Object object, MethodCacheState state) {
-		if(state.method != null) return state.method;
 
-		if(methods.size() > 0) {
-			for (int i = 0; i < state.signatures.length; i++) {
-				state.method = (Method)methods.get(getClassesKey(state.signatures[i].arguments));
-				if(state.method != null) {
-					state.current = state.signatures[i];
-					return state.method;
+	abstract void handleInvocationTargetException(TemplateContext context,
+			InvocationTargetException e);
+
+	abstract void handleIllegalAccessException(TemplateContext context,
+			IllegalAccessException e);
+
+	abstract void handleMethodNotFoundException(TemplateContext context);
+
+	public abstract Class<?> getInvokedClass(TemplateContext context);
+
+	public abstract Object getInvokedObject(TemplateContext context);
+
+	protected Signature provideMethod(TemplateContext context,
+			Class<?>[] parameterTypes) {
+		Class<?> cls = getInvokedClass(context);
+		if (null != cls) {
+			// TODO - cache signatures ?
+			Object object = getInvokedObject(context);
+			Method[] methods = cls.getMethods();
+			for (int m = 0; m < methods.length; m++) {
+				if (methods[m].getName().equals(methodName)
+						&& (object != null || Modifier.isStatic(methods[m]
+								.getModifiers()))) {
+					Signature s = new Signature0(methods[m]);
+					if (s.isApplicable(context, cls, parameterTypes)) {
+						return s;
+					}
+					s = new Signature1(methods[m]);
+					if (s.isApplicable(context, cls, parameterTypes)) {
+						return s;
+					}
+					s = new Signature2(methods[m]);
+					if (s.isApplicable(context, cls, parameterTypes)) {
+						return s;
+					}
 				}
 			}
 		}
-		
-		if(cls == null && object != null) cls = object.getClass();
-		Method[] ms = cls.getMethods();
-		for (int m = 0; m < ms.length; m++) {
-			if(!ms[m].getName().equals(methodName)) continue;
-			if(object == null && !Modifier.isStatic(ms[m].getModifiers())) continue;
-			Class[] cs = ms[m].getParameterTypes();
-			Signature s = getMatchingArguments(cs, state.signatures);
-			if(s == null) continue;
-			state.current = s;
-			state.method = ms[m];
-			methods.put(getClassesKey(s.arguments), ms[m]);
-			return state.method;
-		}
-
+		handleMethodNotFoundException(context);
 		return null;
 	}
 
-	private String getClassesKey(Object[] args) {
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0; i < args.length; i++) {
-			String dk = args[i] == null ? "null" : args[i].getClass().getName();
-			sb.append(";").append(dk);
-		}
-		return sb.toString();
-	}
-	
-	private Signature getMatchingArguments(Class[] cs, Signature[] sgs) {
-		for (int i = 0; i < sgs.length; i++) {
-			if(isMatching(cs, sgs[i].arguments)) return sgs[i];
-		}
-		return null;
-	}
-
-	static boolean isMatching(Class[] cs, Object[] args) {
-		if(cs.length != args.length) return false;
+	static boolean isMatching(Class<?>[] cs, Class<?>[] args) {
+		if (cs.length != args.length)
+			return false;
 		for (int i = 0; i < cs.length; i++) {
-			if(args[i] != null && !cs[i].isAssignableFrom(args[i].getClass())) return false;
+			if (args[i] != null && !cs[i].isAssignableFrom(args[i]))
+				return false;
 		}
 		return true;
 	}
 }
 
 class RendererInvoker extends Invoker {
-	boolean utils = false;
-	Map renderers = new HashMap();
-	
-	public RendererInvoker(boolean utils, String methodName) {
-		this.utils = utils;
-		this.methodName = methodName;
+
+	public RendererInvoker(String methodName) {
+		super(methodName);
 	}
 
-	public Class getInvokedClass(TemplateContext context) {
+	public Class<? extends Object> getInvokedClass(TemplateContext context) {
 		Object object = getInvokedObject(context);
-		return (object != null) ? object.getClass() : null;
+		return (object != null) ? object.getClass() : Renderer.class;
 	}
-	
-	private Object getInvokedObject(TemplateContext context) {
-		if(utils) {
-			return context.getRenderer().getUtils();
-		} else {
-			return context.getRenderer();
-		}
+
+	public Object getInvokedObject(TemplateContext context) {
+		return context.getRenderer();
 	}
-	
-	InvokeData invokeMethod(TemplateContext context, MethodCacheState state) {
+
+	void handleInvocationTargetException(TemplateContext context,
+			InvocationTargetException e) {
+		String logMessage = Messages.getMessage(Messages.METHOD_CALL_ERROR_1a,
+				methodName, context.getComponent().getId());
+		String excMessage = Messages.getMessage(Messages.METHOD_CALL_ERROR_2a,
+				new Object[] { methodName, context.getComponent().getId(),
+						e.getCause().getMessage() });
+		MethodCallElement._log.error(logMessage, e);
+		throw new FacesException(excMessage, e);
+	}
+
+	void handleIllegalAccessException(TemplateContext context,
+			IllegalAccessException e) {
+		String logMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_3a, methodName, context
+						.getComponent().getId()));
+		String excMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_4a, new Object[] { methodName,
+						context.getComponent().getId(),
+						e.getCause().getMessage() }));
+		MethodCallElement._log.error(logMessage, e);
+		throw new FacesException(excMessage, e);
+	}
+
+	void handleMethodNotFoundException(TemplateContext context)
+			throws MethodNotFoundException {
+		String logMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_5a, methodName, context
+						.getComponent().getId()));
+		String excMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_6a, methodName));
+		MethodCallElement._log.error(logMessage);
+		throw new FacesException(excMessage);
+	}
+}
+
+class RendererUtilsInvoker extends RendererInvoker {
+
+	public RendererUtilsInvoker(String methodName) {
+		super(methodName);
+	}
+
+	public Class<? extends Object> getInvokedClass(TemplateContext context) {
 		Object object = getInvokedObject(context);
-		Map methods = getMethods(object);
-		return invokeMethod(context, methods, null, object, state);
+		return (object != null) ? object.getClass() : RendererUtils.class;
 	}
-	
-	private Map getMethods(Object object) {
-		if(object == null) return null;
-		Map methods = (Map)renderers.get(object);
-		if(methods == null) {
-			methods = new HashMap();
-			renderers.put(object, methods);
-		}
-		return methods;
+
+	public Object getInvokedObject(TemplateContext context) {
+		RendererBase renderer = context.getRenderer();
+		return null != renderer ? renderer.getUtils() : null;
 	}
 
-	void handleInvocationTargetException(TemplateContext context, InvocationTargetException e) {
-		String logMessage = (utils) 
-			? Messages.getMessage(Messages.METHOD_CALL_ERROR_1, methodName, context.getComponent().getId())
-			: Messages.getMessage(Messages.METHOD_CALL_ERROR_1a, methodName, context.getComponent().getId());
-		String excMessage = (utils)
-			? Messages.getMessage(Messages.METHOD_CALL_ERROR_2, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()})
-			: Messages.getMessage(Messages.METHOD_CALL_ERROR_2a, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()});
+	void handleInvocationTargetException(TemplateContext context,
+			InvocationTargetException e) {
+		String logMessage = Messages.getMessage(Messages.METHOD_CALL_ERROR_1,
+				methodName, context.getComponent().getId());
+		String excMessage = Messages.getMessage(Messages.METHOD_CALL_ERROR_2,
+				new Object[] { methodName, context.getComponent().getId(),
+						e.getCause().getMessage() });
 		MethodCallElement._log.error(logMessage, e);
 		throw new FacesException(excMessage, e);
 	}
-	void handleIllegalAccessException(TemplateContext context, IllegalAccessException e) {
-		String logMessage = (utils) 
-			? Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_3, methodName, context.getComponent().getId()))
-			: Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_3a, methodName, context.getComponent().getId()));
-		String excMessage = (utils)
-			? Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_4, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()}))
-			: Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_4a, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()}));
+
+	void handleIllegalAccessException(TemplateContext context,
+			IllegalAccessException e) {
+		String logMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_3, methodName, context
+						.getComponent().getId()));
+		String excMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_4, new Object[] { methodName,
+						context.getComponent().getId(),
+						e.getCause().getMessage() }));
 		MethodCallElement._log.error(logMessage, e);
 		throw new FacesException(excMessage, e);
 	}
-	
-	void handleMethodNotFoundException(TemplateContext context) throws MethodNotFoundException {
-		String logMessage = (utils) 
-			? Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_5, methodName, context.getComponent().getId()))
-			: Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_5a, methodName, context.getComponent().getId()));
-		String excMessage = (utils)
-			? Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_6, methodName))
-			: Messages.getMessage(Messages.getMessage(Messages.METHOD_CALL_ERROR_6a, methodName));
-			MethodCallElement._log.error(logMessage);
+
+	void handleMethodNotFoundException(TemplateContext context)
+			throws MethodNotFoundException {
+		String logMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_5, methodName, context
+						.getComponent().getId()));
+		String excMessage = Messages.getMessage(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_6, methodName));
+		MethodCallElement._log.error(logMessage);
 		throw new FacesException(excMessage);
 	}
 }
 
 class StaticInvoker extends Invoker {
 	String className;
-	Class cls;
-	Map methods = new HashMap();
-	
+	Class<?> cls;
+	Map<String, Method> methods = new HashMap<String, Method>();
+
 	StaticInvoker(String methodName) {
-		this.methodName = methodName;
+		super(methodName);
 		int i = methodName.lastIndexOf('.');
 		className = methodName.substring(0, i);
 		this.methodName = methodName.substring(i + 1);
 		try {
-			cls = Thread.currentThread().getContextClassLoader().loadClass(className);
+			cls = Thread.currentThread().getContextClassLoader().loadClass(
+					className);
 		} catch (ClassNotFoundException e) {
-			//ignore, throw exception when invoking
+			// ignore, throw exception when invoking
 		}
 	}
 
-	InvokeData invokeMethod(TemplateContext context, MethodCacheState state) {
-		if(cls == null) throw new FacesException(className, new ClassNotFoundException(className));
-		return invokeMethod(context, methods, cls, null, state);
+	@Override
+	public Class<?> getInvokedClass(TemplateContext context) {
+		return cls;
 	}
 
-	void handleInvocationTargetException(TemplateContext context, InvocationTargetException e) {
-		MethodCallElement._log.error(Messages.getMessage(Messages.METHOD_CALL_ERROR_1a, methodName, context.getComponent().getId()), e);
-		throw new FacesException(Messages.getMessage(Messages.METHOD_CALL_ERROR_2a, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()}), e);
+	@Override
+	public Object getInvokedObject(TemplateContext context) {
+		return null;
 	}
-	void handleIllegalAccessException(TemplateContext context, IllegalAccessException e) {
-		MethodCallElement._log.error(Messages.getMessage(Messages.METHOD_CALL_ERROR_3a, methodName, context.getComponent().getId()), e);
-		throw new FacesException(Messages.getMessage(Messages.METHOD_CALL_ERROR_4a, new Object[]{methodName, context.getComponent().getId(), e.getCause().getMessage()}), e);
-	}		
-	void handleMethodNotFoundException(TemplateContext context) throws MethodNotFoundException {
-		MethodCallElement._log.error(Messages.getMessage(Messages.METHOD_CALL_ERROR_5a, methodName, context.getComponent().getId()));
-		throw new MethodNotFoundException(Messages.getMessage(Messages.METHOD_CALL_ERROR_6a, methodName));
+
+	void handleInvocationTargetException(TemplateContext context,
+			InvocationTargetException e) {
+		MethodCallElement._log.error(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_1a, methodName, context
+						.getComponent().getId()), e);
+		throw new FacesException(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_2a, new Object[] { methodName,
+						context.getComponent().getId(),
+						e.getCause().getMessage() }), e);
 	}
+
+	void handleIllegalAccessException(TemplateContext context,
+			IllegalAccessException e) {
+		MethodCallElement._log.error(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_3a, methodName, context
+						.getComponent().getId()), e);
+		throw new FacesException(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_4a, new Object[] { methodName,
+						context.getComponent().getId(),
+						e.getCause().getMessage() }), e);
+	}
+
+	void handleMethodNotFoundException(TemplateContext context)
+			throws MethodNotFoundException {
+		MethodCallElement._log.error(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_5a, methodName, context
+						.getComponent().getId()));
+		throw new MethodNotFoundException(Messages.getMessage(
+				Messages.METHOD_CALL_ERROR_6a, methodName));
+	}
+
 }
 
-class MethodCacheState {
-	private MethodParameterElement[] elements;
-	private Class[] parameterClasses;
-	private Object[] parameterValues;
-	private Class lastCallingClass = null;
-	public Method method;
-	public Signature current;
-	public Signature[] signatures;
-	
-	public void init(List parameters) {
-		if(elements != null) return;
-		synchronized (this) {
-			if(elements != null) return;
-			int size = parameters.size();
-			parameterClasses = new Class[size];
-			parameterValues = new Object[size];
-			signatures = new Signature[3];
-			signatures[0] = new Signature2(size);
-			signatures[1] = new Signature1(size);
-			signatures[2] = new Signature0(size);		
-			elements = (MethodParameterElement[])parameters.toArray(new MethodParameterElement[0]);
-		}
+abstract class Signature {
+
+	Method method;
+
+	Signature(Method method) {
+		this.method = method;
 	}
-	
-	public Object[] computeParameterValues(TemplateContext context) {
-		Object[] ps = new Object[elements.length];
-		for (int i = 0; i < elements.length; i++) {
-			ps[i] = elements[i].valueGetter.getValueOrDefault(context);
+
+	boolean isApplicable(TemplateContext context, Class targetClass,
+			Class<?>[] parameters) {
+		if (!method.getDeclaringClass().isAssignableFrom(targetClass)) {
+			return false;
 		}
-		return ps;
-	}
-	
-	public void update(TemplateContext context, Object[] values, Invoker invoker) {
-		boolean changed = false;
-		for (int i = 0; i < elements.length; i++) {
-			Object parametr = values[i];
-			Class c = (parametr == null) ? null : parametr.getClass();
-			if(c != parameterClasses[i]) {
-				parameterClasses[i] = c;
-				changed = true;
-			}
-			parameterValues[i] = parametr;			
+		Class<?>[] methodParameterTypes = this.method.getParameterTypes();
+		Class<?>[] parameterTypes = getParameterTypes(context, parameters);
+		if (methodParameterTypes.length != parameterTypes.length) {
+			return false;
 		}
-		if(method != null && !changed && lastCallingClass != invoker.getInvokedClass(context)) {
-			lastCallingClass = invoker.getInvokedClass(context);
-			changed = true;
-		}
-		if(changed || current == null) {
-			for (int i = 0; i < signatures.length; i++) {
-				signatures[i].update(context, parameterValues);
+		for (int i = 0; i < parameterTypes.length; i++) {
+			if (null != parameterTypes[i]
+					&& !methodParameterTypes[i]
+							.isAssignableFrom(parameterTypes[i])) {
+				return false;
 			}
-			method = null;
-			current = null;
-		} else {
-			current.update(context, parameterValues);
 		}
-	}	
-	
-}
+		return true;
+	}
 
-abstract class Signature {
-	Object[] arguments;	
+	abstract Class<?>[] getParameterTypes(TemplateContext context,
+			Class<?>[] parameters);
 
-	Signature() {}
+	abstract Object[] getParameterValues(TemplateContext context,
+			Object[] parameters);
 
-	void update(TemplateContext context, Object[] parameters) {}
+	Object invoke(TemplateContext context, Object target, Object[] parameters)
+			throws IllegalArgumentException, IllegalAccessException,
+			InvocationTargetException {
+		return this.method.invoke(target, getParameterValues(context,
+				parameters));
+	}
+
 }
 
 class Signature0 extends Signature {
-	Signature0(int size) {
-		arguments = new Object[size];
+
+	Signature0(Method method) {
+		super(method);
 	}
 
-	void update(TemplateContext context, Object[] parameters) {
-		System.arraycopy(parameters, 0, arguments, 0, parameters.length);
+	@Override
+	Class<?>[] getParameterTypes(TemplateContext context, Class<?>[] parameters) {
+		return parameters;
 	}
-	
+
+	@Override
+	Object[] getParameterValues(TemplateContext context, Object[] parameters) {
+		return parameters;
+	}
+
 }
 
 class Signature1 extends Signature {
-	Signature1(int size) {
-		arguments = new Object[size + 1];
+	Signature1(Method method) {
+		super(method);
 	}
-	void update(TemplateContext context, Object[] parameters) {
-		arguments[0] = context;
-		System.arraycopy(parameters, 0, arguments, 1, parameters.length);
+
+	@Override
+	Class<?>[] getParameterTypes(TemplateContext context, Class<?>[] parameters) {
+		Class<?>[] types = new Class[parameters.length + 1];
+		types[0] = TemplateContext.class;
+		System.arraycopy(parameters, 0, types, 1, parameters.length);
+		return types;
 	}
-	
+
+	@Override
+	Object[] getParameterValues(TemplateContext context, Object[] parameters) {
+		Object[] values = new Object[parameters.length + 1];
+		values[0] = context;
+		System.arraycopy(parameters, 0, values, 1, parameters.length);
+		return values;
+	}
+
 }
 
 class Signature2 extends Signature {
-	Signature2(int size) {
-		arguments = new Object[size + 2];
+	Signature2(Method method) {
+		super(method);
 	}
-	void update(TemplateContext context, Object[] parameters) {
-		arguments[0] = context.getFacesContext();
-		arguments[1] = context.getComponent();
-		System.arraycopy(parameters, 0, arguments, 2, parameters.length);
-	}	
+
+	@Override
+	Class<?>[] getParameterTypes(TemplateContext context, Class<?>[] parameters) {
+		Class<?>[] types = new Class[parameters.length + 2];
+		types[0] = FacesContext.class;
+		types[1] = context.getComponent().getClass();
+		System.arraycopy(parameters, 0, types, 2, parameters.length);
+		return types;
+	}
+
+	@Override
+	Object[] getParameterValues(TemplateContext context, Object[] parameters) {
+		Object[] values = new Object[parameters.length + 2];
+		values[0] = context.getFacesContext();
+		values[1] = context.getComponent();
+		System.arraycopy(parameters, 0, values, 2, parameters.length);
+		return values;
+	}
 }



More information about the richfaces-svn-commits mailing list