|
JMeter example source code file (Functor.java)
The JMeter Functor.java source code/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * */ package org.apache.jorphan.reflect; import java.lang.reflect.Method; import java.util.Arrays; import org.apache.jorphan.logging.LoggingManager; import org.apache.jorphan.util.JMeterError; import org.apache.log.Logger; /** * Implements function call-backs. * * Functors may be defined for instance objects or classes. * * The method is created on first use, which allows the invokee (class or instance) * to be omitted from the constructor. * * The class name takes precedence over the instance. * * If a functor is created with a particular instance, then that is used for all future calls; * if an object is provided, it is ignored. * This allows easy override of the table model behaviour. * * If an argument list is provided in the constructor, then that is ignored in subsequent invoke() calls. * * Usage: * f = new Functor("methodName") * o = f.invoke(object) - OR - * o = f.invoke(object,params) * * f2 = new Functor(object,"methodName"); * o = f2.invoke() - OR - * o = f2.invoke(params) * * f3 = new Functor(class,"methodName"); * o = f3.invoke(object) - will be ignored * o = f3.invoke() - OR - * o = f3.invoke(params) * o = f3.invoke(object,params) - object will be ignored * */ public class Functor { private static final Logger log = LoggingManager.getLoggerForClass(); /* * If non-null, then any object provided to invoke() is ignored. */ private final Object invokee; /* * Class to be used to create the Method. * Will be non-null if either Class or Object was provided during construction. * * Can be used instead of invokee, e.g. when using interfaces. */ private final Class<?> clazz; // Methondname must always be provided. private final String methodName; /* * If non-null, then any argument list passed to invoke() will be ignored. */ private Object[] args; /* * Argument types used to create the method. * May be provided explicitly, or derived from the constructor argument list. */ private final Class<?>[] types; /* * This depends on the class or invokee and either args or types; * it is set once by doCreateMethod(), which must be the only method to access it. */ private Method methodToInvoke; Functor(){ throw new IllegalArgumentException("Must provide at least one argument"); } /** * Create a functor with the invokee and a method name. * * The invokee will be used in all future invoke calls. * * @param _invokee object on which to invoke the method * @param _methodName method name */ public Functor(Object _invokee, String _methodName) { this(null, _invokee, _methodName, null, null); } /** * Create a functor from class and method name. * This is useful for methods defined in interfaces. * * The actual invokee must be provided in all invoke() calls, * and must be an instance of the class. * * @param _clazz class to be used * @param _methodName method name */ public Functor(Class<?> _clazz, String _methodName) { this(_clazz, null, _methodName, null, null); } /** * Create a functor with the invokee, method name, and argument class types. * * The invokee will be ignored in any invoke() calls. * * @param _invokee object on which to invoke the method * @param _methodName method name * @param _types */ public Functor(Object _invokee, String _methodName, Class<?>[] _types) { this(null, _invokee, _methodName, null, _types); } /** * Create a functor with the class, method name, and argument class types. * * Subsequent invoke() calls must provide the appropriate ivokee object. * * @param _clazz the class in which to find the method * @param _methodName method name * @param _types */ public Functor(Class<?> _clazz, String _methodName, Class>[] _types) { this(_clazz, null, _methodName, null, _types); } /** * Create a functor with just the method name. * * The invokee and any parameters must be provided in all invoke() calls. * * @param _methodName method name */ public Functor(String _methodName) { this(null, null, _methodName, null, null); } /** * Create a functor with the method name and argument class types. * * The invokee must be provided in all invoke() calls * * @param _methodName method name * @param _types parameter types */ public Functor(String _methodName, Class<?>[] _types) { this(null, null, _methodName, null, _types); } /** * Create a functor with an invokee, method name, and argument values. * * The invokee will be ignored in any invoke() calls. * * @param _invokee object on which to invoke the method * @param _methodName method name * @param _args arguments to be passed to the method */ public Functor(Object _invokee, String _methodName, Object[] _args) { this(null, _invokee, _methodName, _args, null); } /** * Create a functor from method name and arguments. * * The class will be determined from the first invoke call. * All invoke calls must include a target object; * which must be of the same type as the initial invokee. * * @param _methodName method name * @param _args */ public Functor(String _methodName, Object[] _args) { this(null, null, _methodName, _args, null); } /** * Create a functor from various different combinations of parameters. * * @param _clazz class containing the method * @param _invokee invokee to use for the method call * @param _methodName the method name (required) * @param _args arguments to be used * @param _types types of arguments to be used * * @throws IllegalArgumentException if: * - methodName is null * - both class and invokee are specified * - both arguments and types are specified */ private Functor(Class<?> _clazz, Object _invokee, String _methodName, Object[] _args, Class>[] _types) { if (_methodName == null){ throw new IllegalArgumentException("Methodname must not be null"); } if (_clazz != null && _invokee != null){ throw new IllegalArgumentException("Cannot provide both Class and Object"); } if (_args != null && _types != null){ throw new IllegalArgumentException("Cannot provide both arguments and argument types"); } // If class not provided, default to invokee class, else null this.clazz = _clazz != null ? _clazz : (_invokee != null ? _invokee.getClass() : null); this.invokee = _invokee; this.methodName = _methodName; this.args = _args; // If types not provided, default to argument types, else null this.types = _types != null ? _types : (_args != null ? _getTypes(_args) : null); } ////////////////////////////////////////// /* * Low level invocation routine. * * Should only be called after any defaults have been applied. * */ private Object doInvoke(Class<?> _class, Object _invokee, Object[] _args) { Class<?>[] argTypes = getTypes(_args); try { Method method = doCreateMethod(_class , argTypes); if (method == null){ final String message = "Can't find method " +_class.getName()+"#"+methodName+typesToString(argTypes); log.error(message, new Throwable()); throw new JMeterError(message); } return method.invoke(_invokee, _args); } catch (Exception e) { final String message = "Trouble functing: " +_class.getName() +"."+methodName+"(...) : " +" invokee: "+_invokee +" "+e.getMessage(); log.warn(message, e); throw new JMeterError(message,e); } } /** * Invoke a Functor, which must have been created with either a class name or object. * * @return the object if any */ public Object invoke() { if (invokee == null) { throw new IllegalStateException("Cannot call invoke() - invokee not known"); } // If invokee was provided, then clazz has been set up return doInvoke(clazz, invokee, getArgs()); } /** * Invoke the method on a given object. * * @param p_invokee - provides the object to call; ignored if the class or object were provided to the constructor * @return the value */ public Object invoke(Object p_invokee) { return invoke(p_invokee, getArgs()); } /** * Invoke the method with the provided parameters. * * The invokee must have been provided in the constructor. * * @param p_args parameters for the method * @return the value */ public Object invoke(Object[] p_args) { if (invokee == null){ throw new IllegalStateException("Invokee was not provided in constructor"); } // If invokee was provided, then clazz has been set up return doInvoke(clazz, invokee, args != null? args : p_args); } /** * Invoke the method on the invokee with the provided parameters. * * The invokee must agree with the class (if any) provided at construction time. * * If the invokee was provided at construction time, then this invokee will be ignored. * If actual arguments were provided at construction time, then arguments will be ignored. * */ public Object invoke(Object p_invokee, Object[] p_args) { return doInvoke(clazz != null ? clazz : p_invokee.getClass(), // Use constructor class if present invokee != null ? invokee : p_invokee, // use invokee if provided args != null? args : p_args);// use argumenrs if provided } /* * Low-level (recursive) routine to define the method - if not already defined. * Synchronized to protect access to methodToInvoke. */ private synchronized Method doCreateMethod(Class<?> p_class, Class>[] p_types) { if (log.isDebugEnabled()){ log.debug("doCreateMethod() using "+this.toString() +"class=" + p_class.getName() + " types: " + Arrays.asList(p_types)); } if (methodToInvoke == null) { try { methodToInvoke = p_class.getMethod(methodName, p_types); } catch (Exception e) { for (int i = 0; i < p_types.length; i++) { Class<?> primitive = getPrimitive(p_types[i]); if (primitive != null) { methodToInvoke = doCreateMethod(p_class, getNewArray(i, primitive, p_types)); if (methodToInvoke != null) { return methodToInvoke; } } Class<?>[] interfaces = p_types[i].getInterfaces(); for (int j = 0; j < interfaces.length; j++) { methodToInvoke = doCreateMethod(p_class,getNewArray(i, interfaces[j], p_types)); if (methodToInvoke != null) { return methodToInvoke; } } Class<?> parent = p_types[i].getSuperclass(); if (parent != null) { methodToInvoke = doCreateMethod(p_class,getNewArray(i, parent, p_types)); if (methodToInvoke != null) { return methodToInvoke; } } } } } return methodToInvoke; } /** * Check if a read Functor method is valid. * * @deprecated ** for use by Unit test code only ** * * @return true if method exists */ @Deprecated public boolean checkMethod(Object _invokee){ Method m = null; try { m = doCreateMethod(_invokee.getClass(), getTypes(args)); } catch (Exception e){ // ignored } return null != m; } /** * Check if a write Functor method is valid. * * @deprecated ** for use by Unit test code only ** * * @return true if method exists */ @Deprecated public boolean checkMethod(Object _invokee, Class<?> c){ Method m = null; try { m = doCreateMethod(_invokee.getClass(), new Class[]{c}); } catch (Exception e){ // ignored } return null != m; } @Override public String toString(){ StringBuilder sb = new StringBuilder(100); if (clazz != null){ sb.append(clazz.getName()); } if (invokee != null){ sb.append("@"); sb.append(System.identityHashCode(invokee)); } sb.append("."); sb.append(methodName); typesToString(sb,types); return sb.toString(); } private void typesToString(StringBuilder sb,Class<?>[] _types) { sb.append("("); if (_types != null){ for(int i=0; i < _types.length; i++){ if (i>0) { sb.append(","); } sb.append(_types[i].getName()); } } sb.append(")"); } private String typesToString(Class<?>[] argTypes) { StringBuilder sb = new StringBuilder(); typesToString(sb,argTypes); return sb.toString(); } private Class<?> getPrimitive(Class> t) { if (t==null) { return null; } if (t.equals(Integer.class)) { return int.class; } else if (t.equals(Long.class)) { return long.class; } else if (t.equals(Double.class)) { return double.class; } else if (t.equals(Float.class)) { return float.class; } else if (t.equals(Byte.class)) { return byte.class; } else if (t.equals(Boolean.class)) { return boolean.class; } else if (t.equals(Short.class)) { return short.class; } else if (t.equals(Character.class)) { return char.class; } return null; } private Class<?>[] getNewArray(int i, Class> replacement, Class>[] orig) { Class<?>[] newArray = new Class[orig.length]; for (int j = 0; j < newArray.length; j++) { if (j == i) { newArray[j] = replacement; } else { newArray[j] = orig[j]; } } return newArray; } private Class<?>[] getTypes(Object[] _args) { if (types == null) { return _getTypes(_args); } return types; } private static Class<?>[] _getTypes(Object[] _args) { Class<?>[] _types; if (_args != null) { _types = new Class[_args.length]; for (int i = 0; i < _args.length; i++) { _types[i] = _args[i].getClass(); } } else { _types = new Class[0]; } return _types; } private Object[] getArgs() { if (args == null) { args = new Object[0]; } return args; } } Other JMeter examples (source code examples)Here is a short list of links related to this JMeter Functor.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.