diff --git a/build.properties b/build.properties index 3be05e87e5..c8ff4b5d3f 100644 --- a/build.properties +++ b/build.properties @@ -7,7 +7,7 @@ ivy.cache.dir=${basedir}/../ivy-cache integration.repo.dir=${basedir}/../integration-repo javadoc.exclude.package.names=org/springframework/samples/** javadoc.max.memory=256M -test.vm.args=-XX:MaxPermSize=128M +test.vm.args=-Xmx1024M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError compiler.args=-enableJavadoc -warn:none # For when releasing diff --git a/org.springframework.beans/src/test/java/test/beans/GenericBean.java b/org.springframework.beans/src/test/java/test/beans/GenericBean.java index e7ee977d5c..25f61c4aa7 100644 --- a/org.springframework.beans/src/test/java/test/beans/GenericBean.java +++ b/org.springframework.beans/src/test/java/test/beans/GenericBean.java @@ -225,7 +225,6 @@ public class GenericBean { this.customEnum = customEnum; } - public static GenericBean createInstance(Set integerSet) { return new GenericBean(integerSet); } diff --git a/org.springframework.context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java b/org.springframework.context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java index f1b7febaf2..37859ee783 100644 --- a/org.springframework.context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java +++ b/org.springframework.context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java @@ -63,7 +63,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource { public ManagedAttribute getManagedAttribute(Method method) throws InvalidMetadataException { org.springframework.jmx.export.annotation.ManagedAttribute ann = - AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class); + AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedAttribute.class); if (ann == null) { return null; } @@ -77,7 +77,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource { public ManagedMetric getManagedMetric(Method method) throws InvalidMetadataException { org.springframework.jmx.export.annotation.ManagedMetric ann = - AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class); + AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedMetric.class); if (ann == null) { return null; } @@ -92,7 +92,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource { throw new InvalidMetadataException( "The ManagedOperation attribute is not valid for JavaBean properties. Use ManagedAttribute instead."); } - Annotation ann = AnnotationUtils.getAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class); + Annotation ann = AnnotationUtils.findAnnotation(method, org.springframework.jmx.export.annotation.ManagedOperation.class); if (ann == null) { return null; } @@ -104,7 +104,7 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource { public ManagedOperationParameter[] getManagedOperationParameters(Method method) throws InvalidMetadataException { - ManagedOperationParameters params = AnnotationUtils.getAnnotation(method, ManagedOperationParameters.class); + ManagedOperationParameters params = AnnotationUtils.findAnnotation(method, ManagedOperationParameters.class); ManagedOperationParameter[] result = null; if (params == null) { result = new ManagedOperationParameter[0]; diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java index be94642571..e410880e59 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationMetadataAssemblerTests.java @@ -16,17 +16,32 @@ package org.springframework.jmx.export.annotation; +import javax.management.modelmbean.ModelMBeanInfo; +import javax.management.modelmbean.ModelMBeanAttributeInfo; +import javax.management.modelmbean.ModelMBeanOperationInfo; + import org.springframework.jmx.IJmxTestBean; import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests; import org.springframework.jmx.export.metadata.JmxAttributeSource; -/** - * @author Rob Harrop - */ +/** @author Rob Harrop */ public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests { private static final String OBJECT_NAME = "bean:name=testBean4"; + public void testAttributeFromInterface() throws Exception { + ModelMBeanInfo inf = getMBeanInfoFromAssembler(); + ModelMBeanAttributeInfo attr = inf.getAttribute("Colour"); + assertTrue("The name attribute should be writable", attr.isWritable()); + assertTrue("The name attribute should be readable", attr.isReadable()); + } + + public void testOperationFromInterface() throws Exception { + ModelMBeanInfo inf = getMBeanInfoFromAssembler(); + ModelMBeanOperationInfo op = inf.getOperation("fromInterface"); + assertNotNull(op); + } + protected JmxAttributeSource getAttributeSource() { return new AnnotationJmxAttributeSource(); } @@ -36,11 +51,20 @@ public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerT } protected IJmxTestBean createJmxTestBean() { - return new AnnotationTestBean(); + return new AnnotationTestSubBean(); } protected String getApplicationContextPath() { return "org/springframework/jmx/export/annotation/annotations.xml"; } + @Override + protected int getExpectedAttributeCount() { + return super.getExpectedAttributeCount() + 1; + } + + @Override + protected int getExpectedOperationCount() { + return super.getExpectedOperationCount() + 3; + } } diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestSubBean.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestSubBean.java new file mode 100644 index 0000000000..0768a96da3 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestSubBean.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * 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.springframework.jmx.export.annotation; + +/** + * @author Rob Harrop + */ +public class AnnotationTestSubBean extends AnnotationTestBean implements IAnnotationTestBean { + + private String colour; + + @Override + public long myOperation() { + return 123L; + } + + @Override + public void setAge(int age) { + super.setAge(age); + } + + @Override + public int getAge() { + return super.getAge(); + } + + public String getColour() { + return this.colour; + } + + public void setColour(String colour) { + this.colour = colour; + } + + public void fromInterface() { + } +} diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/IAnnotationTestBean.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/IAnnotationTestBean.java new file mode 100644 index 0000000000..9afa121cd6 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/IAnnotationTestBean.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * 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.springframework.jmx.export.annotation; + +/** + * @author Rob Harrop + */ +public interface IAnnotationTestBean { + + @ManagedAttribute + String getColour(); + + @ManagedAttribute + void setColour(String colour); + + @ManagedOperation + void fromInterface(); +} diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/annotations.xml b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/annotations.xml index 7e044ed9d0..c9c15cf771 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/annotations.xml +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/annotations.xml @@ -19,7 +19,7 @@ - + TEST diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java index a73ecd9585..3c15e835ee 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/assembler/AbstractMetadataAssemblerTests.java @@ -18,6 +18,7 @@ package org.springframework.jmx.export.assembler; import java.util.HashMap; import java.util.Map; +import java.util.Arrays; import javax.management.Descriptor; import javax.management.MBeanInfo; diff --git a/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index f67071365b..de46417e1a 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -101,6 +101,9 @@ public abstract class AnnotationUtils { public static A findAnnotation(Method method, Class annotationType) { A annotation = getAnnotation(method, annotationType); Class cl = method.getDeclaringClass(); + if(annotation == null) { + annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces()); + } while (annotation == null) { cl = cl.getSuperclass(); if (cl == null || cl == Object.class) { @@ -109,6 +112,9 @@ public abstract class AnnotationUtils { try { Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes()); annotation = getAnnotation(equivalentMethod, annotationType); + if(annotation == null) { + annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces()); + } } catch (NoSuchMethodException ex) { // We're done... @@ -117,6 +123,24 @@ public abstract class AnnotationUtils { return annotation; } + private static A searchForAnnotationOnInterfaces(Method method, Class annotationType, Class[] ifaces) { + A annotation = null; + for (Class iface : ifaces) { + Method equivalentMethod = null; + try { + equivalentMethod = iface.getDeclaredMethod(method.getName(), method.getParameterTypes()); + annotation = getAnnotation(equivalentMethod, annotationType); + } + catch (NoSuchMethodException e) { + // skip this interface - it doesn't have the method + } + if (annotation != null) { + break; + } + } + return annotation; + } + /** * Find a single {@link Annotation} of annotationType from the * supplied {@link Class}, traversing its interfaces and super classes diff --git a/org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java b/org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java index 7c142146ab..e131c72f3c 100644 --- a/org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java +++ b/org.springframework.core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java @@ -188,6 +188,22 @@ public class AnnotationUtilsTests { assertEquals(Ordered.LOWEST_PRECEDENCE, AnnotationUtils.getDefaultValue(Order.class)); } + @Test + public void testFindAnnotationFromInterface() throws Exception { + + Method method = ImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo"); + Order order = findAnnotation(method, Order.class); + assertNotNull(order); + } + + @Test + public void testFindAnnotationFromInterfaceOnSuper() throws Exception { + + Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo"); + Order order = findAnnotation(method, Order.class); + assertNotNull(order); + } + public static interface AnnotatedInterface { @Order(0) @@ -286,6 +302,25 @@ public class AnnotationUtilsTests { public static class SubNonInheritedAnnotationClass extends NonInheritedAnnotationClass { } + + public static interface InterfaceWithAnnotatedMethod { + + @Order + void foo(); + } + + public static class ImplementsInterfaceWithAnnotatedMethod implements InterfaceWithAnnotatedMethod { + + public void foo() { + } + } + + public static class SubOfImplementsInterfaceWithAnnotatedMethod extends ImplementsInterfaceWithAnnotatedMethod { + + public void foo() { + } + } + } @Retention(RetentionPolicy.RUNTIME)