001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.weaver.utils; 020 021import java.lang.annotation.Annotation; 022import java.lang.reflect.InvocationHandler; 023import java.lang.reflect.Method; 024import java.lang.reflect.Proxy; 025import java.util.Arrays; 026import java.util.Map; 027 028import org.apache.commons.lang3.AnnotationUtils; 029import org.apache.commons.lang3.Validate; 030 031/** 032 * Provide annotation-related utility methods. 033 */ 034public final class Annotations { 035 private Annotations() { 036 } 037 038 /** 039 * Create an annotation instance. 040 * @param annotationType type 041 * @param elements values 042 * @param <A> generic annotation type 043 * @return {@code A} 044 */ 045 public static <A extends Annotation> A instanceOf(final Class<A> annotationType, final Map<String, ?> elements) { 046 final ClassLoader proxyClassLoader = Validate.notNull(annotationType, "annotationType").getClassLoader(); 047 final InvocationHandler invocationHandler = new InvocationHandler() { 048 049 @Override 050 @SuppressWarnings("PMD.UseVarargs") // overridden method 051 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 052 if (method.getDeclaringClass().equals(annotationType)) { 053 if (elements.containsKey(method.getName())) { 054 return elements.get(method.getName()); 055 } 056 return method.getDefaultValue(); 057 } 058 if ("annotationType".equals(method.getName()) && method.getParameterTypes().length == 0) { 059 return annotationType; 060 } 061 if ("equals".equals(method.getName()) 062 && Arrays.equals(method.getParameterTypes(), new Class[] { Object.class })) { 063 return AnnotationUtils.equals((Annotation) proxy, (Annotation) args[0]); 064 } 065 if ("hashCode".equals(method.getName()) && method.getParameterTypes().length == 0) { 066 return AnnotationUtils.hashCode((Annotation) proxy); 067 } 068 if ("toString".equals(method.getName()) && method.getParameterTypes().length == 0) { 069 return AnnotationUtils.toString((Annotation) proxy); 070 } 071 throw new UnsupportedOperationException(); 072 } 073 }; 074 @SuppressWarnings("unchecked") 075 final A result = 076 (A) Proxy.newProxyInstance(proxyClassLoader, new Class[] { annotationType }, invocationHandler); 077 return result; 078 } 079}