Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* #%L
* %%
* Copyright (C) 2011 - 2017 BMW Car IT GmbH
* %%
* Licensed 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.
* #L%
*/
package io.joynr.dispatcher.rpc;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods for the reflection part of Joyn-RPC
*/
public class ReflectionUtils {
/**
* Utility function to find a method in a class by name.
*
* @param parameterTypes
*
* @return any method in the class that has the specified method name
*/
private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);
private static final String BYTE = "Byte";
private static final String SHORT = "Short";
private static final String INTEGER = "Integer";
private static final String LONG = "Long";
private static final String FLOAT = "Float";
private static final String DOUBLE = "Double";
private static final String STRING = "String";
private static final String BOOLEAN = "Boolean";
public static List findMethodsByName(Class> clazz, String methodName) throws NoSuchMethodException {
ArrayList methodsList = new ArrayList(Arrays.asList(clazz.getDeclaredMethods()));
if (methodsList.isEmpty()) {
throw new NoSuchMethodException(methodName);
}
for (Iterator iterator = methodsList.iterator(); iterator.hasNext();) {
Method method = iterator.next();
if (!method.getName().equals(methodName)) {
iterator.remove();
}
}
return methodsList;
}
public static Method findMethodByParamTypes(Class> clazz,
String methodName,
Class>[] parameterTypes) throws NoSuchMethodException {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
if (checkParameterTypes(method, parameterTypes)) {
return method;
}
}
}
throw new NoSuchMethodException(methodName);
}
private static boolean checkParameterTypes(Method method, Class>[] parameterTypes) {
Class>[] currentMethodParamTypes = method.getParameterTypes();
if (currentMethodParamTypes.length != parameterTypes.length) {
return false;
}
for (int i = 0; i < parameterTypes.length; i++) {
if (!currentMethodParamTypes[i].isAssignableFrom(parameterTypes[i])) {
return false;
}
}
return true;
}
public static Method findMethodByParamTypeNames(Class> clazz,
String methodName,
List paramTypeNames) throws NoSuchMethodException {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
if (checkParameterTypeNames(method, paramTypeNames)) {
return method;
}
}
}
throw new NoSuchMethodException(methodName);
}
private static boolean checkParameterTypeNames(Method method, List paramTypeNames) {
if (paramTypeNames == null) {
String msg = "Received RPC without parameter types list! Method overloading might cause unexpected behaviour!";
logger.error(msg);
throw new IllegalArgumentException(msg);
}
String[] currentMethodParamTypes = toDatatypeNames(method.getParameterTypes());
if (paramTypeNames.size() != currentMethodParamTypes.length) {
return false;
}
for (int i = 0; i < currentMethodParamTypes.length; i++) {
String currentParamName = currentMethodParamTypes[i];
String matchingParamName = paramTypeNames.get(i);
if (!currentParamName.equals(matchingParamName)) {
return false;
}
}
return true;
}
/**
* Utility function to find all annotations on the parameters of the specified method and merge them with the same
* annotations on all base classes and interfaces.
*
* @param method the method in question
* @return the list of annotations for this method
*/
public static List> findAndMergeParameterAnnotations(Method method) {
List> res = new ArrayList>(method.getParameterTypes().length);
for (int i = 0; i < method.getParameterTypes().length; i++) {
res.add(new LinkedList());
}
findAndMergeAnnotations(method.getDeclaringClass(), method, res);
return res;
}
private static void findAndMergeAnnotations(Class> clazz, Method method, List> res) {
Method[] methods = clazz.getDeclaredMethods();
for (Method currentMethod : methods) {
if (areMethodNameAndParameterTypesEqual(currentMethod, method)) {
for (int i = 0; i < currentMethod.getParameterAnnotations().length; i++) {
for (Annotation annotation : currentMethod.getParameterAnnotations()[i]) {
res.get(i).add(annotation);
}
}
}
}
for (Class> interfaceClass : clazz.getInterfaces()) {
findAndMergeAnnotations(interfaceClass, method, res);
}
if (clazz.getSuperclass() != null) {
findAndMergeAnnotations(clazz.getSuperclass(), method, res);
}
}
/**
* Compares to methods for equality based on name and parameter types.
*/
private static boolean areMethodNameAndParameterTypesEqual(Method methodA, Method methodB) {
if (!methodA.getName().equals(methodB.getName())) {
return false;
}
Class>[] methodAParameterTypes = methodA.getParameterTypes();
Class>[] methodBParameterTypes = methodB.getParameterTypes();
if (methodAParameterTypes.length != methodBParameterTypes.length) {
return false;
}
for (int i = 0; i < methodAParameterTypes.length; i++) {
if (!methodAParameterTypes[i].equals(methodBParameterTypes[i])) {
return false;
}
}
return true;
}
public static String[] toDatatypeNames(Class>... types) {
if (types == null) {
return null;
}
String[] strings = new String[types.length];
for (int i = 0; i < types.length; i++) {
Class> type = types[i];
if (type == null) {
continue;
} else {
strings[i] = type.getCanonicalName().replace("java.lang.", "");
}
}
return strings;
}
public static Class>[] toJavaClasses(String... typeNames) {
if (typeNames == null) {
return null;
}
Class>[] classes = new Class[typeNames.length];
for (int i = 0; i < typeNames.length; i++) {
String[] nameTokens = typeNames[i].split("\\[");
Class> clazz;
switch (nameTokens[0]) {
case BOOLEAN:
clazz = Boolean.class;
break;
case BYTE:
clazz = Byte.class;
break;
case SHORT:
clazz = Short.class;
break;
case INTEGER:
clazz = Integer.class;
break;
case LONG:
clazz = Long.class;
break;
case FLOAT:
clazz = Float.class;
break;
case DOUBLE:
clazz = Double.class;
break;
case STRING:
clazz = String.class;
break;
default:
try {
clazz = Class.forName(nameTokens[0]);
} catch (ClassNotFoundException e) {
logger.debug("class not found", e);
clazz = Object.class;
}
break;
}
clazz = processArrayTokens(clazz, nameTokens.length - 1);
classes[i] = clazz;
}
return classes;
}
private static Class> processArrayTokens(Class> clazz, int i) {
if (i == 0) {
return clazz;
}
return processArrayTokens(Array.newInstance(clazz, 0).getClass(), --i);
}
}