Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit a09ccae

Browse files
author
Petr Bouda
committed
Introducing AnnotationLiteral in injection spi.
Change-Id: If003e1fb134ebefadc5edc1a8cbcd82dc97f4dcd
1 parent 7ed19f2 commit a09ccae

File tree

21 files changed

+298
-52
lines changed

21 files changed

+298
-52
lines changed

core-client/src/main/java/org/glassfish/jersey/client/ClientAsyncExecutorLiteral.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2015-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -39,7 +39,7 @@
3939
*/
4040
package org.glassfish.jersey.client;
4141

42-
import org.glassfish.hk2.api.AnnotationLiteral;
42+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
4343

4444
/**
4545
* {@link org.glassfish.jersey.client.ClientAsyncExecutor} annotation literal.

core-common/src/main/java/org/glassfish/jersey/internal/inject/CustomAnnotationLiteral.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2012-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -39,7 +39,7 @@
3939
*/
4040
package org.glassfish.jersey.internal.inject;
4141

42-
import org.glassfish.hk2.api.AnnotationLiteral;
42+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
4343

4444
/**
4545
* {@link Custom} annotation literal.
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
/*
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3+
*
4+
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
5+
*
6+
* The contents of this file are subject to the terms of either the GNU
7+
* General Public License Version 2 only ("GPL") or the Common Development
8+
* and Distribution License("CDDL") (collectively, the "License"). You
9+
* may not use this file except in compliance with the License. You can
10+
* obtain a copy of the License at
11+
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
12+
* or packager/legal/LICENSE.txt. See the License for the specific
13+
* language governing permissions and limitations under the License.
14+
*
15+
* When distributing the software, include this License Header Notice in each
16+
* file and include the License file at packager/legal/LICENSE.txt.
17+
*
18+
* GPL Classpath Exception:
19+
* Oracle designates this particular file as subject to the "Classpath"
20+
* exception as provided by Oracle in the GPL Version 2 section of the License
21+
* file that accompanied this code.
22+
*
23+
* Modifications:
24+
* If applicable, add the following below the License Header, with the fields
25+
* enclosed by brackets [] replaced by your own identifying information:
26+
* "Portions Copyright [year] [name of copyright owner]"
27+
*
28+
* Contributor(s):
29+
* If you wish your version of this file to be governed by only the CDDL or
30+
* only the GPL Version 2, indicate your decision by adding "[Contributor]
31+
* elects to include this software in this distribution under the [CDDL or GPL
32+
* Version 2] license." If you don't indicate a single choice of license, a
33+
* recipient has the option to distribute your version of this file under
34+
* either the CDDL, the GPL Version 2 or to extend the choice of license to
35+
* its licensees as provided above. However, if you add GPL Version 2 code
36+
* and therefore, elected the GPL Version 2 license, then the option applies
37+
* only if the new code is made subject to such option by the copyright
38+
* holder.
39+
*/
40+
package org.glassfish.jersey.spi.inject;
41+
42+
import java.io.Serializable;
43+
import java.lang.annotation.Annotation;
44+
import java.lang.reflect.AccessibleObject;
45+
import java.lang.reflect.InvocationTargetException;
46+
import java.lang.reflect.Method;
47+
import java.lang.reflect.ParameterizedType;
48+
import java.lang.reflect.Type;
49+
import java.security.AccessController;
50+
import java.security.PrivilegedAction;
51+
import java.util.Arrays;
52+
53+
/**
54+
* Supports inline instantiation of annotation type instances.
55+
* <p>
56+
* An instance of an annotation type may be obtained by subclassing <tt>AnnotationLiteral</tt>.
57+
* <pre>
58+
* public abstract class PayByQualifier
59+
* extends AnnotationLiteral&lt;PayBy&gt;
60+
* implements PayBy {}
61+
* </pre>
62+
* An extension of AnnotationLiteral must do two things:<OL>
63+
* <LI>Must have the target annotation as its generic type</LI>
64+
* <LI>Must implement the target type</LI>
65+
* </OL>
66+
* In particular, in-line anonymous extensions of AnnotationLiteral will not
67+
* work because in-line anonymous extensions of AnnotationLiteral cannot implement
68+
* the target annotation
69+
*
70+
* @param <T> the annotation type
71+
* @author jwells
72+
*/
73+
public abstract class AnnotationLiteral<T extends Annotation> implements Annotation, Serializable {
74+
75+
private static final long serialVersionUID = -3645430766814376616L;
76+
77+
private transient Class<T> annotationType;
78+
private transient Method[] members;
79+
80+
protected AnnotationLiteral() {
81+
Class<?> thisClass = this.getClass();
82+
83+
boolean foundAnnotation = false;
84+
for (Class<?> iClass : thisClass.getInterfaces()) {
85+
if (iClass.isAnnotation()) {
86+
foundAnnotation = true;
87+
break;
88+
}
89+
}
90+
91+
if (!foundAnnotation) {
92+
throw new IllegalStateException(
93+
"The subclass " + thisClass.getName() + " of AnnotationLiteral must implement an Annotation");
94+
}
95+
}
96+
97+
private static Class<?> getAnnotationLiteralSubclass(Class<?> clazz) {
98+
Class<?> superclass = clazz.getSuperclass();
99+
if (superclass.equals(AnnotationLiteral.class)) {
100+
return clazz;
101+
} else if (superclass.equals(Object.class)) {
102+
return null;
103+
} else {
104+
return getAnnotationLiteralSubclass(superclass);
105+
}
106+
}
107+
108+
@SuppressWarnings("unchecked")
109+
private static <T> Class<T> getTypeParameter(Class<?> annotationLiteralSuperclass) {
110+
Type type = annotationLiteralSuperclass.getGenericSuperclass();
111+
if (type instanceof ParameterizedType) {
112+
ParameterizedType parameterizedType = (ParameterizedType) type;
113+
if (parameterizedType.getActualTypeArguments().length == 1) {
114+
return (Class<T>) parameterizedType.getActualTypeArguments()[0];
115+
}
116+
}
117+
return null;
118+
}
119+
120+
private static void setAccessible(final AccessibleObject ao) {
121+
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
122+
ao.setAccessible(true);
123+
return null;
124+
});
125+
}
126+
127+
private static Object invoke(Method method, Object instance) {
128+
try {
129+
if (!method.isAccessible()) {
130+
setAccessible(method);
131+
}
132+
return method.invoke(instance);
133+
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
134+
throw new RuntimeException(
135+
"Error checking value of member method " + method.getName() + " on " + method.getDeclaringClass(), e);
136+
}
137+
}
138+
139+
private Method[] getMembers() {
140+
if (members == null) {
141+
members = AccessController.doPrivileged((PrivilegedAction<Method[]>) annotationType()::getDeclaredMethods);
142+
143+
if (members.length > 0 && !annotationType().isAssignableFrom(this.getClass())) {
144+
throw new RuntimeException(
145+
getClass() + " does not implement the annotation type with members " + annotationType().getName());
146+
}
147+
}
148+
return members;
149+
}
150+
151+
/**
152+
* Method returns the type of the annotation literal. The value is resolved lazily during the first call of this method.
153+
*
154+
* @return annotation type of this literal.
155+
*/
156+
public Class<? extends Annotation> annotationType() {
157+
if (annotationType == null) {
158+
Class<?> annotationLiteralSubclass = getAnnotationLiteralSubclass(this.getClass());
159+
if (annotationLiteralSubclass == null) {
160+
throw new RuntimeException(getClass() + "is not a subclass of AnnotationLiteral");
161+
}
162+
annotationType = getTypeParameter(annotationLiteralSubclass);
163+
if (annotationType == null) {
164+
throw new RuntimeException(getClass() + " does not specify the type parameter T of AnnotationLiteral<T>");
165+
}
166+
}
167+
return annotationType;
168+
}
169+
170+
@Override
171+
public boolean equals(Object other) {
172+
if (other instanceof Annotation) {
173+
Annotation that = (Annotation) other;
174+
if (this.annotationType().equals(that.annotationType())) {
175+
for (Method member : getMembers()) {
176+
Object thisValue = invoke(member, this);
177+
Object thatValue = invoke(member, that);
178+
if (thisValue instanceof byte[] && thatValue instanceof byte[]) {
179+
if (!Arrays.equals((byte[]) thisValue, (byte[]) thatValue)) {
180+
return false;
181+
}
182+
} else if (thisValue instanceof short[] && thatValue instanceof short[]) {
183+
if (!Arrays.equals((short[]) thisValue, (short[]) thatValue)) {
184+
return false;
185+
}
186+
} else if (thisValue instanceof int[] && thatValue instanceof int[]) {
187+
if (!Arrays.equals((int[]) thisValue, (int[]) thatValue)) {
188+
return false;
189+
}
190+
} else if (thisValue instanceof long[] && thatValue instanceof long[]) {
191+
if (!Arrays.equals((long[]) thisValue, (long[]) thatValue)) {
192+
return false;
193+
}
194+
} else if (thisValue instanceof float[] && thatValue instanceof float[]) {
195+
if (!Arrays.equals((float[]) thisValue, (float[]) thatValue)) {
196+
return false;
197+
}
198+
} else if (thisValue instanceof double[] && thatValue instanceof double[]) {
199+
if (!Arrays.equals((double[]) thisValue, (double[]) thatValue)) {
200+
return false;
201+
}
202+
} else if (thisValue instanceof char[] && thatValue instanceof char[]) {
203+
if (!Arrays.equals((char[]) thisValue, (char[]) thatValue)) {
204+
return false;
205+
}
206+
} else if (thisValue instanceof boolean[] && thatValue instanceof boolean[]) {
207+
if (!Arrays.equals((boolean[]) thisValue, (boolean[]) thatValue)) {
208+
return false;
209+
}
210+
} else if (thisValue instanceof Object[] && thatValue instanceof Object[]) {
211+
if (!Arrays.equals((Object[]) thisValue, (Object[]) thatValue)) {
212+
return false;
213+
}
214+
} else {
215+
if (!thisValue.equals(thatValue)) {
216+
return false;
217+
}
218+
}
219+
}
220+
return true;
221+
}
222+
}
223+
return false;
224+
}
225+
226+
@Override
227+
public int hashCode() {
228+
229+
int hashCode = 0;
230+
for (Method member : getMembers()) {
231+
int memberNameHashCode = 127 * member.getName().hashCode();
232+
Object value = invoke(member, this);
233+
int memberValueHashCode;
234+
if (value instanceof boolean[]) {
235+
memberValueHashCode = Arrays.hashCode((boolean[]) value);
236+
} else if (value instanceof short[]) {
237+
memberValueHashCode = Arrays.hashCode((short[]) value);
238+
} else if (value instanceof int[]) {
239+
memberValueHashCode = Arrays.hashCode((int[]) value);
240+
} else if (value instanceof long[]) {
241+
memberValueHashCode = Arrays.hashCode((long[]) value);
242+
} else if (value instanceof float[]) {
243+
memberValueHashCode = Arrays.hashCode((float[]) value);
244+
} else if (value instanceof double[]) {
245+
memberValueHashCode = Arrays.hashCode((double[]) value);
246+
} else if (value instanceof byte[]) {
247+
memberValueHashCode = Arrays.hashCode((byte[]) value);
248+
} else if (value instanceof char[]) {
249+
memberValueHashCode = Arrays.hashCode((char[]) value);
250+
} else if (value instanceof Object[]) {
251+
memberValueHashCode = Arrays.hashCode((Object[]) value);
252+
} else {
253+
memberValueHashCode = value.hashCode();
254+
}
255+
hashCode += memberNameHashCode ^ memberValueHashCode;
256+
}
257+
return hashCode;
258+
}
259+
260+
}

core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
* make sure to delegate the lifecycle listener calls further to all the container lifecycle listeners registered within the
170170
* application. Additionally, invoking the {@link ContainerLifecycleListener#onShutdown(Container)} method on this application
171171
* handler instance will release all the resources associated with the underlying application instance as well as close the
172-
* application-specific {@link org.glassfish.hk2.api.ServiceLocator HK2 ServiceLocator}.
172+
* application-specific {@link InstanceManager instance manager}.
173173
* </p>
174174
*
175175
* @author Pavel Bucek (pavel.bucek at oracle.com)

core-server/src/main/java/org/glassfish/jersey/server/BackgroundSchedulerLiteral.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2015-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -39,7 +39,7 @@
3939
*/
4040
package org.glassfish.jersey.server;
4141

42-
import org.glassfish.hk2.api.AnnotationLiteral;
42+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
4343

4444
/**
4545
* {@link BackgroundScheduler} annotation literal.

core-server/src/main/java/org/glassfish/jersey/server/ManagedAsyncExecutorLiteral.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2015-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -39,7 +39,7 @@
3939
*/
4040
package org.glassfish.jersey.server;
4141

42-
import org.glassfish.hk2.api.AnnotationLiteral;
42+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
4343

4444
/**
4545
* {@link ManagedAsyncExecutor} annotation literal.

examples/entity-filtering/src/main/java/org/glassfish/jersey/examples/entityfiltering/filtering/ProjectDetailedView.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -47,8 +47,7 @@
4747
import java.lang.annotation.Target;
4848

4949
import org.glassfish.jersey.message.filtering.EntityFiltering;
50-
51-
import org.glassfish.hk2.api.AnnotationLiteral;
50+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
5251

5352
/**
5453
* Entity-filtering annotation used to define detailed view on returned

examples/entity-filtering/src/main/java/org/glassfish/jersey/examples/entityfiltering/filtering/TaskDetailedView.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -47,8 +47,7 @@
4747
import java.lang.annotation.Target;
4848

4949
import org.glassfish.jersey.message.filtering.EntityFiltering;
50-
51-
import org.glassfish.hk2.api.AnnotationLiteral;
50+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
5251

5352
/**
5453
* Entity-filtering annotation used to define detailed view on returned

examples/entity-filtering/src/main/java/org/glassfish/jersey/examples/entityfiltering/filtering/UserDetailedView.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -47,8 +47,7 @@
4747
import java.lang.annotation.Target;
4848

4949
import org.glassfish.jersey.message.filtering.EntityFiltering;
50-
51-
import org.glassfish.hk2.api.AnnotationLiteral;
50+
import org.glassfish.jersey.spi.inject.AnnotationLiteral;
5251

5352
/**
5453
* Entity-filtering annotation used to define detailed view on returned

0 commit comments

Comments
 (0)