diff --git a/pom.xml b/pom.xml index 5b6e5e9..ad01a05 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,11 @@ com.google.inject guice + + org.apache.commons + commons-lang3 + 3.12.0 + org.jenkins-ci annotation-indexer diff --git a/src/main/java/com/cloudbees/sdk/extensibility/AnnotationLiteral.java b/src/main/java/com/cloudbees/sdk/extensibility/AnnotationLiteral.java index e0fb7d9..740d00d 100644 --- a/src/main/java/com/cloudbees/sdk/extensibility/AnnotationLiteral.java +++ b/src/main/java/com/cloudbees/sdk/extensibility/AnnotationLiteral.java @@ -17,7 +17,10 @@ package com.cloudbees.sdk.extensibility; import java.lang.annotation.Annotation; +import java.lang.reflect.Proxy; import java.util.Collections; +import java.util.Map; +import org.apache.commons.lang3.AnnotationUtils; /** * Factory for annotation objects. @@ -41,4 +44,26 @@ public static T of(Class type, Object value) { public static T of(Class type, String key, Object value) { return of(type, Collections.singletonMap(key, value)); } + + public static T of(Class type, final Map values) { + return type.cast(Proxy.newProxyInstance(type.getClassLoader(), new Class[] {type}, (proxy, method, args) -> { + Annotation annotation = (Annotation) proxy; + String methodName = method.getName(); + switch (methodName) { + case "equals": + return AnnotationUtils.equals(annotation, (Annotation) args[0]); + case "toString": + return AnnotationUtils.toString(annotation); + case "hashCode": + return AnnotationUtils.hashCode(annotation); + case "annotationType": + return type; + default: + if (!values.containsKey(methodName)) { + throw new NoSuchMethodException("Missing value for annotation key: " + methodName); + } + return values.get(methodName); + } + })); + } } diff --git a/src/test/java/com/cloudbees/sdk/extensibility/AnnotationLiteralTest.java b/src/test/java/com/cloudbees/sdk/extensibility/AnnotationLiteralTest.java new file mode 100644 index 0000000..969d66f --- /dev/null +++ b/src/test/java/com/cloudbees/sdk/extensibility/AnnotationLiteralTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2023, CloudBees Inc. + * + * 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 com.cloudbees.sdk.extensibility; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import javax.inject.Named; +import org.junit.Test; + +/** + * @author Basil Crow + */ +public class AnnotationLiteralTest { + @Test + public void smokes() { + Named a = AnnotationLiteral.of(Named.class, "cat"); + assertEquals("@javax.inject.Named(value=cat)", a.toString()); + assertEquals(Named.class, a.annotationType()); + + Named cat = Cat.class.getAnnotation(Named.class); + assertEquals(a, cat); + assertEquals(a.hashCode(), cat.hashCode()); + + Named dog = Dog.class.getAnnotation(Named.class); + assertNotEquals(a, dog); + assertNotEquals(a.hashCode(), dog.hashCode()); + } +}