/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.translator.coherence.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.teiid.core.util.ReflectionHelper;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.coherence.CoherencePlugin;
/**
* ObjectSourceMethodManager caches the methods for the classes that
* are being utilized, and provides utility methods for finding a method
* and executing.
*/
public class ObjectSourceMethodManager {
private static ObjectSourceMethodManager osmm = new ObjectSourceMethodManager();
private Map<Class<?>, Method[]> classToMethodMap = new ConcurrentHashMap<Class<?>, Method[]>();
public ObjectSourceMethodManager() {
}
/**
* Call to execute the method
*
* @param m
* is the method to execute
* @param api
* is the object to execute the method on
* @param parms
* are the parameters to pass when the method is executed
* @return Object return value
* @throws Exception
*/
public static Object executeMethod(Method m, Object api, Object[] parms)
throws TranslatorException {
try {
return m.invoke(api, parms);
} catch (InvocationTargetException x) {
x.printStackTrace();
Throwable cause = x.getCause();
System.err.format("invocation of %s failed: %s%n",
"set" + m.getName(), cause.getMessage());
LogManager.logError(LogConstants.CTX_CONNECTOR, "Error calling "
+ m.getName() + ":" + cause.getMessage());
throw new TranslatorException(x.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new TranslatorException(e.getMessage());
}
}
/**
* Call to execute the method
*
* @param m
* is the method to execute
* @param api
* is the object to execute the method on
* @param parms
* are the parameters to pass when the method is executed
* @return Object return value
* @throws Exception
*/
public static Object executeMethod(Method m, Object api, List parms)
throws TranslatorException {
try {
return m.invoke(api, parms.toArray());
} catch (InvocationTargetException x) {
x.printStackTrace();
Throwable cause = x.getCause();
System.err.format("invocation of %s failed: %s%n",
"set" + m.getName(), cause.getMessage());
LogManager.logError(LogConstants.CTX_CONNECTOR, "Error calling "
+ m.getName() + ":" + cause.getMessage());
throw new TranslatorException(x.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new TranslatorException(e.getMessage());
}
}
public static Object createObject(String objectClassName)
throws TranslatorException {
try {
return ReflectionHelper.create(objectClassName, null, null);
} catch (Exception e1) {
throw new TranslatorException(e1);
}
}
public static Object getValue(String methodName, Object object)
throws TranslatorException {
try {
final Method m = osmm
.getMethod(object.getClass(), methodName, null);
return m.invoke(object, (Object[]) null);
} catch (TranslatorException t) {
throw t;
} catch (InvocationTargetException x) {
Throwable cause = x.getCause();
System.err.format("invocation of %s failed: %s%n", "get"
+ methodName, cause.getMessage());
LogManager.logError(LogConstants.CTX_CONNECTOR, "Error calling get"
+ methodName + ":" + cause.getMessage());
throw new TranslatorException(x.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new TranslatorException(e.getMessage());
}
}
public static Method getMethod(Class api, String methodName, List argumentsClasses)
throws TranslatorException {
try {
Method[] namedMethods = findMethods(methodName, getMethodsFromAPI(api));
if (namedMethods != null && namedMethods.length == 1) {
return namedMethods[0];
}
Method m = findBestMethod(api, methodName, argumentsClasses);
if (m == null) {
throw new NoSuchMethodException(
CoherencePlugin.Util
.getString(
"ObjectSourceMethodManager.No_method_implemented_for", new Object[] {methodName, api.getName()})); //$NON-NLS-1$
}
return m;
} catch (NoSuchMethodException nsme) {
String msg = CoherencePlugin.Util
.getString(
"ObjectSourceMethodManager.No_method_implemented_for", new Object[] {methodName, api.getName()});
throw new TranslatorException(msg); //$NON-NLS-1$
} catch (Exception e) {
final String msg = CoherencePlugin.Util.getString("ObjectSourceMethodManager.No_method_implemented_for", new Object[] {methodName, api.getName()}); //$NON-NLS-1$
throw new TranslatorException(msg);
}
}
private static Method[] findMethods(String methodName, Method[] methods) {
if (methods == null || methods.length == 0) {
return null;
}
final ArrayList result = new ArrayList();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(methodName)) {
result.add(methods[i]);
}
}
return (Method[]) result.toArray(new Method[result.size()]);
}
private static synchronized Method[] getMethodsFromAPI(Class api)
throws SecurityException {
Method[] ms = osmm.classToMethodMap.get(api);
if (ms != null) {
return ms;
}
Method[] methods = api.getMethods();
osmm.classToMethodMap.put(api, methods);
return methods;
}
/**
* Call to find the best method on a class, by passing the
* cache
* @param objectClass
* @param methodName
* @param argumentsClasses
* @return
* @throws TranslatorException
*/
private static Method findBestMethod(Class objectClass, String methodName,
List argumentsClasses) throws SecurityException, NoSuchMethodException {
ReflectionHelper rh = new ReflectionHelper(objectClass);
if (argumentsClasses == null) {
argumentsClasses = Collections.EMPTY_LIST;
}
return rh.findBestMethodWithSignature(methodName, argumentsClasses);
}
}