mirror of https://github.com/apache/openjpa.git
OPENJPA-251, OPENJPA-329. svn merge -c 616961 ../branches/1.0.x/
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@617191 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d24bec6ed6
commit
18e83a09b1
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.openjpa.enhance;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that {@link Reflection#getDeclaredMethod(Class, String, Class)}
|
||||||
|
* returns the most-derived class's method when called from a type hierarchy.
|
||||||
|
* See OPENJPA-251.
|
||||||
|
*/
|
||||||
|
public class TestGetDeclaredMethod extends TestCase {
|
||||||
|
|
||||||
|
public void testGetDeclaredMethod() {
|
||||||
|
Method meth =
|
||||||
|
Reflection.getDeclaredMethod(Impl.class, "getObject", null);
|
||||||
|
assertEquals(Impl.class, meth.getDeclaringClass());
|
||||||
|
assertEquals(String.class, meth.getReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMostDerived() throws NoSuchMethodException {
|
||||||
|
Method impl = Impl.class.getDeclaredMethod("getObject", null);
|
||||||
|
Method iface = Iface.class.getDeclaredMethod("getObject", null);
|
||||||
|
Method other = Other.class.getDeclaredMethod("getObject", null);
|
||||||
|
assertEquals(Impl.class, Reflection.mostDerived(impl, iface)
|
||||||
|
.getDeclaringClass());
|
||||||
|
assertEquals(Impl.class, Reflection.mostDerived(iface, impl)
|
||||||
|
.getDeclaringClass());
|
||||||
|
try {
|
||||||
|
Reflection.mostDerived(iface, other);
|
||||||
|
fail("'iface' and 'other' are not from related types");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGenerics() throws NoSuchMethodException {
|
||||||
|
List<Method> meths = new ArrayList<Method>();
|
||||||
|
for (Method meth : GenericsImpl.class.getDeclaredMethods()) {
|
||||||
|
if ("getObject".equals(meth.getName()))
|
||||||
|
meths.add(meth);
|
||||||
|
}
|
||||||
|
assertEquals(2, meths.size());
|
||||||
|
assertEquals(String.class, Reflection.mostDerived(meths.get(0),
|
||||||
|
meths.get(1)).getReturnType());
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Iface {
|
||||||
|
Object getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Impl implements Iface {
|
||||||
|
public String getObject() {
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Other {
|
||||||
|
public String getObject() {
|
||||||
|
return "other";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GenericsIface<T> {
|
||||||
|
public T getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class GenericsImpl implements GenericsIface {
|
||||||
|
public String getObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -112,25 +112,60 @@ public class Reflection {
|
||||||
* Invokes <code>cls.getDeclaredMethods()</code>, and returns the method
|
* Invokes <code>cls.getDeclaredMethods()</code>, and returns the method
|
||||||
* that matches the <code>name</code> and <code>param</code> arguments.
|
* that matches the <code>name</code> and <code>param</code> arguments.
|
||||||
* Avoids the exception thrown by <code>Class.getDeclaredMethod()</code>
|
* Avoids the exception thrown by <code>Class.getDeclaredMethod()</code>
|
||||||
* for performance reasons. <code>param</code> may be null.
|
* for performance reasons. <code>param</code> may be null. Additionally,
|
||||||
|
* if there are multiple methods with different return types, this will
|
||||||
|
* return the method defined in the least-derived class.
|
||||||
*
|
*
|
||||||
* @since 0.9.8
|
* @since 0.9.8
|
||||||
*/
|
*/
|
||||||
private static Method getDeclaredMethod(Class cls, String name,
|
static Method getDeclaredMethod(Class cls, String name,
|
||||||
Class param) {
|
Class param) {
|
||||||
Method[] methods = (Method[]) AccessController.doPrivileged(
|
Method[] methods = (Method[]) AccessController.doPrivileged(
|
||||||
J2DoPrivHelper.getDeclaredMethodsAction(cls));
|
J2DoPrivHelper.getDeclaredMethodsAction(cls));
|
||||||
|
Method candidate = null;
|
||||||
for (int i = 0 ; i < methods.length; i++) {
|
for (int i = 0 ; i < methods.length; i++) {
|
||||||
if (name.equals(methods[i].getName())) {
|
if (name.equals(methods[i].getName())) {
|
||||||
Class[] methodParams = methods[i].getParameterTypes();
|
Class[] methodParams = methods[i].getParameterTypes();
|
||||||
if (param == null && methodParams.length == 0)
|
if (param == null && methodParams.length == 0)
|
||||||
return methods[i];
|
candidate = mostDerived(methods[i], candidate);
|
||||||
if (param != null && methodParams.length == 1
|
else if (param != null && methodParams.length == 1
|
||||||
&& param.equals(methodParams[0]))
|
&& param.equals(methodParams[0]))
|
||||||
return methods[i];
|
candidate = mostDerived(methods[i], candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Method mostDerived(Method meth1, Method meth2) {
|
||||||
|
if (meth1 == null)
|
||||||
|
return meth2;
|
||||||
|
if (meth2 == null)
|
||||||
|
return meth1;
|
||||||
|
|
||||||
|
Class cls2 = meth2.getDeclaringClass();
|
||||||
|
Class cls1 = meth1.getDeclaringClass();
|
||||||
|
|
||||||
|
if (cls1.equals(cls2)) {
|
||||||
|
Class ret1 = meth1.getReturnType();
|
||||||
|
Class ret2 = meth2.getReturnType();
|
||||||
|
if (ret1.isAssignableFrom(ret2))
|
||||||
|
return meth2;
|
||||||
|
else if (ret2.isAssignableFrom(ret1))
|
||||||
|
return meth1;
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
_loc.get("most-derived-unrelated-same-type", meth1, meth2)
|
||||||
|
.getMessage());
|
||||||
|
} else {
|
||||||
|
if (cls1.isAssignableFrom(cls2))
|
||||||
|
return meth2;
|
||||||
|
else if (cls2.isAssignableFrom(cls1))
|
||||||
|
return meth1;
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
_loc.get("most-derived-unrelated", meth1, meth2)
|
||||||
|
.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -199,3 +199,8 @@ unspecified-unenhanced-types: The following classes were not specified in your \
|
||||||
configuration: {1}. One or more of the classes that were registered with \
|
configuration: {1}. One or more of the classes that were registered with \
|
||||||
the system had references to these classes. Registered types: {0}
|
the system had references to these classes. Registered types: {0}
|
||||||
enhance-error: An error occurred while enhancing {0}. Exception message: {1}
|
enhance-error: An error occurred while enhancing {0}. Exception message: {1}
|
||||||
|
most-derived-unrelated: Methods "{0}" and "{1}" are defined in types that do \
|
||||||
|
not have an interface or superclass inheritance relationship.
|
||||||
|
most-derived-unrelated-same-type: Methods "{0}" and "{1}" are defined in the same \
|
||||||
|
type, but the method return types do not have an interface or superclass \
|
||||||
|
inheritance relationship.
|
||||||
|
|
Loading…
Reference in New Issue