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

Commit b37dfa1

Browse files
committed
MessageBodyWorker comparator needs to handle Object differently.
Object is used as the furthest type, there can't be anything farther than that. Change-Id: Ib57c08dfe30a368974600a0f6cc17bd1a271d5f1
1 parent e9ee1a3 commit b37dfa1

File tree

2 files changed

+160
-1
lines changed

2 files changed

+160
-1
lines changed

core-common/src/main/java/org/glassfish/jersey/message/internal/MessageBodyFactory.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,18 @@ private Iterator<Class<?>> getClassHierarchyIterator(final Class<?> classParam)
435435
final ArrayList<Class<?>> classes = new ArrayList<>();
436436
final LinkedList<Class<?>> unprocessed = new LinkedList<>();
437437

438+
// Object is special - needs to be always the furthest type.
439+
boolean objectFound = false;
440+
438441
unprocessed.add(classParam);
439442
while (!unprocessed.isEmpty()) {
440443
final Class<?> clazz = unprocessed.removeFirst();
441444

442-
classes.add(clazz);
445+
if (Object.class.equals(clazz)) {
446+
objectFound = true;
447+
} else {
448+
classes.add(clazz);
449+
}
443450
unprocessed.addAll(Arrays.asList(clazz.getInterfaces()));
444451

445452
final Class<?> superclazz = clazz.getSuperclass();
@@ -448,6 +455,10 @@ private Iterator<Class<?>> getClassHierarchyIterator(final Class<?> classParam)
448455
}
449456
}
450457

458+
if (objectFound) {
459+
classes.add(Object.class);
460+
}
461+
451462
return classes.iterator();
452463
}
453464
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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+
41+
package org.glassfish.jersey.tests.e2e.common;
42+
43+
import java.io.IOException;
44+
import java.io.OutputStream;
45+
import java.lang.annotation.Annotation;
46+
import java.lang.reflect.Type;
47+
48+
import javax.ws.rs.GET;
49+
import javax.ws.rs.Path;
50+
import javax.ws.rs.Produces;
51+
import javax.ws.rs.WebApplicationException;
52+
import javax.ws.rs.core.Application;
53+
import javax.ws.rs.core.MediaType;
54+
import javax.ws.rs.core.MultivaluedMap;
55+
import javax.ws.rs.ext.MessageBodyWriter;
56+
import javax.ws.rs.ext.Provider;
57+
58+
import org.glassfish.jersey.server.ResourceConfig;
59+
import org.glassfish.jersey.test.JerseyTest;
60+
61+
import org.junit.Test;
62+
import static org.junit.Assert.assertEquals;
63+
64+
/**
65+
* Object.class needs special handling when computing type distance - it should be always further than any other
66+
* implemented interface.
67+
*
68+
* @author Pavel Bucek (pavel.bucek at oracle.com)
69+
*/
70+
@SuppressWarnings("WeakerAccess")
71+
public class MessageBodyWriterObjectDistanceTest extends JerseyTest {
72+
73+
public interface InterfaceA {
74+
75+
}
76+
77+
public interface InterfaceB extends InterfaceA {
78+
79+
}
80+
81+
@Provider
82+
@Produces("application/test")
83+
public static class ObjectWriter implements MessageBodyWriter<Object> {
84+
85+
@Override
86+
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
87+
return true;
88+
}
89+
90+
@Override
91+
public long getSize(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
92+
return -1;
93+
}
94+
95+
@Override
96+
public void writeTo(Object o, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
97+
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
98+
WebApplicationException {
99+
entityStream.write("object".getBytes("UTF-8"));
100+
}
101+
}
102+
103+
@Provider
104+
@Produces("application/test")
105+
public static class InterfaceAWriter implements MessageBodyWriter<InterfaceA> {
106+
@Override
107+
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
108+
return InterfaceA.class.isAssignableFrom(type);
109+
}
110+
111+
@Override
112+
public long getSize(InterfaceA interfaceA, Class<?> type, Type genericType, Annotation[] annotations,
113+
MediaType mediaType) {
114+
return -1;
115+
}
116+
117+
@Override
118+
public void writeTo(InterfaceA interfaceA, Class<?> type, Type genericType, Annotation[] annotations,
119+
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
120+
throws IOException, WebApplicationException {
121+
entityStream.write(InterfaceA.class.getSimpleName().getBytes("UTF-8"));
122+
}
123+
}
124+
125+
@Path("resource")
126+
public static class Resource {
127+
128+
@GET
129+
@Produces("application/test")
130+
public InterfaceB getStringModel() {
131+
return new InterfaceB() {
132+
};
133+
}
134+
}
135+
136+
@Override
137+
protected Application configure() {
138+
return new ResourceConfig(Resource.class)
139+
.register(ObjectWriter.class)
140+
.register(InterfaceAWriter.class);
141+
}
142+
143+
@Test
144+
public void testMessageBodyWriterObjectDistance() throws Exception {
145+
assertEquals(InterfaceA.class.getSimpleName(),
146+
target().path("resource").request("application/test").get(String.class));
147+
}
148+
}

0 commit comments

Comments
 (0)