1
7 package org.hibernate.validator.internal.util.annotation;
8
9 import java.io.Serializable;
10 import java.lang.annotation.Annotation;
11 import java.lang.reflect.InvocationHandler;
12 import java.lang.reflect.Method;
13 import java.lang.reflect.Proxy;
14 import java.security.AccessController;
15 import java.security.PrivilegedAction;
16 import java.util.Arrays;
17 import java.util.Map;
18 import java.util.Map.Entry;
19
20 import org.hibernate.validator.internal.util.privilegedactions.GetAnnotationAttributes;
21
22
41 class AnnotationProxy implements Annotation, InvocationHandler, Serializable {
42
43 private static final long serialVersionUID = 6907601010599429454L;
44
45 private final AnnotationDescriptor<? extends Annotation> descriptor;
46
47 AnnotationProxy(AnnotationDescriptor<? extends Annotation> descriptor) {
48 this.descriptor = descriptor;
49 }
50
51 @Override
52 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
53 Object value = descriptor.getAttribute( method.getName() );
54 if ( value != null ) {
55 return value;
56 }
57 return method.invoke( this, args );
58 }
59
60 @Override
61 public Class<? extends Annotation> annotationType() {
62 return descriptor.getType();
63 }
64
65
74 @Override
75 public boolean equals(Object obj) {
76 if ( this == obj ) {
77 return true;
78 }
79 if ( obj == null ) {
80 return false;
81 }
82 if ( !descriptor.getType().isInstance( obj ) ) {
83 return false;
84 }
85
86 Annotation other = descriptor.getType().cast( obj );
87
88 Map<String, Object> otherAttributes = getAnnotationAttributes( other );
89
90 if ( descriptor.getAttributes().size() != otherAttributes.size() ) {
91 return false;
92 }
93
94
95 for ( Entry<String, Object> member : descriptor.getAttributes().entrySet() ) {
96 Object value = member.getValue();
97 Object otherValue = otherAttributes.get( member.getKey() );
98
99 if ( !areEqual( value, otherValue ) ) {
100 return false;
101 }
102 }
103
104 return true;
105 }
106
107
115 @Override
116 public int hashCode() {
117 return descriptor.hashCode();
118 }
119
120 @Override
121 public String toString() {
122 return descriptor.toString();
123 }
124
125 private boolean areEqual(Object o1, Object o2) {
126 return
127 !o1.getClass().isArray() ? o1.equals( o2 )
128 : o1.getClass() == boolean[].class ? Arrays.equals( (boolean[]) o1, (boolean[]) o2 )
129 : o1.getClass() == byte[].class ? Arrays.equals( (byte[]) o1, (byte[]) o2 )
130 : o1.getClass() == char[].class ? Arrays.equals( (char[]) o1, (char[]) o2 )
131 : o1.getClass() == double[].class ? Arrays.equals( (double[]) o1, (double[]) o2 )
132 : o1.getClass() == float[].class ? Arrays.equals( (float[]) o1, (float[]) o2 )
133 : o1.getClass() == int[].class ? Arrays.equals( (int[]) o1, (int[]) o2 )
134 : o1.getClass() == long[].class ? Arrays.equals( (long[]) o1, (long[]) o2 )
135 : o1.getClass() == short[].class ? Arrays.equals( (short[]) o1, (short[]) o2 )
136 : Arrays.equals( (Object[]) o1, (Object[]) o2 );
137 }
138
139 private Map<String, Object> getAnnotationAttributes(Annotation annotation) {
140
141
142 if ( Proxy.isProxyClass( annotation.getClass() ) && System.getSecurityManager() == null ) {
143 InvocationHandler invocationHandler = Proxy.getInvocationHandler( annotation );
144 if ( invocationHandler instanceof AnnotationProxy ) {
145 return ( (AnnotationProxy) invocationHandler ).descriptor.getAttributes();
146 }
147 }
148
149 return run( GetAnnotationAttributes.action( annotation ) );
150 }
151
152
158 private <T> T run(PrivilegedAction<T> action) {
159 return System.getSecurityManager() != null ? AccessController.doPrivileged( action ) : action.run();
160 }
161 }
162