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());
+ }
+}