/*
* 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.
*/
package org.gwtwidgets.server.spring;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.google.gwt.user.client.rpc.RemoteService;
/**
* Utilities for internal use
*
* @author Dmitri Shestakov, dvshestakov[at]gmail.com
* @author Daniel Spangler
* @author George Georgovassilis, g.georgovassilis[at]gmail.com
*
*/
public class ReflectionUtils {
/**
* Return array of all interfaces that are implemented by clazz and extend
* {@link RemoteService}.
*
* @param clazz Class to scan for interfaces
* @return Array of interfaces. May be empty but never null.
*/
@SuppressWarnings("unchecked")
public static Class<RemoteService>[] getExposedInterfaces(Class<?> clazz) {
Set<Class<?>> interfaces = getInterfaces(clazz);
for (Iterator<Class<?>> ite = interfaces.iterator(); ite.hasNext();) {
Class<?> c = ite.next();
if (!isExposed(c))
ite.remove();
}
return interfaces.toArray(new Class[interfaces.size()]);
}
/**
* Adds elements of an array to a set. The JRE 1.5 does include a similar
* method in the Collections class, but that breaks GWT-SL 1.4
* compatibility.
*
* @param set Set of classes
* @param elements Elements in this array will be added to the set
*/
public static void addAll(Set<Class<?>> set, Class<?>[] elements) {
for (Class<?> element : elements)
set.add(element);
}
/**
* Return all interfaces that are implemented by this class, traversing
* super classes and super interfaces.
*
* @param c Class to scan
* @return Set of classes. May be empty but not null.
*/
public static Set<Class<?>> getInterfaces(Class<?> c) {
Class<?> interfaces[] = c.getInterfaces();
Set<Class<?>> classes = new HashSet<Class<?>>();
if (interfaces == null)
return classes;
addAll(classes, interfaces);
for (Class<?> cl : interfaces) {
classes.addAll(getInterfaces(cl));
}
Class<?> superClass = c.getSuperclass();
if (superClass != null) {
classes.addAll(getInterfaces(superClass));
}
return classes;
}
private static boolean isExposed(Class<?> c) {
return RemoteService.class.isAssignableFrom(c);
}
/**
* Will try to find method in 'serviceInterfaces' and if found, will attempt
* to return a method with the same signature from 'service', otherwise an
* exception is thrown. If 'serviceInterfaces' is a zero-sized array, the
* interface check is omitted and the method is looked up directly on the
* object.
*
* @param target
* Object to search method on
* @param serviceInterfaces
* The requested method must exist on at least one of the
* interfaces
* @param method Method to look for
* @return Method on 'service' or else a {@link NoSuchMethodException} is
* thrown
* @throws NoSuchMethodException If method can't be found on target
*/
public static Method getRPCMethod(Object target, Class<?>[] serviceInterfaces, Method method) throws NoSuchMethodException {
if (serviceInterfaces.length == 0)
return target.getClass().getMethod(method.getName(), method.getParameterTypes());
for (Class<?> serviceInterface : serviceInterfaces)
try {
Method template = serviceInterface.getMethod(method.getName(), method.getParameterTypes());
return target.getClass().getMethod(template.getName(), template.getParameterTypes());
} catch (NoSuchMethodException e) {
}
throw new NoSuchMethodException(method.toString());
}
/*
* This is from the AnnotationUtils class of the Springframework (2.5+) in
* the core packag. This code is licensed under the Apache v2 license.
*/
public static <A extends Annotation> A findAnnotation(Class<?> clazz,
Class<A> annotationType) {
A annotation = clazz.getAnnotation(annotationType);
if (annotation != null) {
return annotation;
}
for (Class<?> ifc : clazz.getInterfaces()) {
annotation = findAnnotation(ifc, annotationType);
if (annotation != null) {
return annotation;
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass == null || superClass == Object.class) {
return null;
}
return findAnnotation(superClass, annotationType);
}
}