Author: sergeyb
Date: Wed Mar 27 14:46:58 2013
New Revision: 1461617
URL: http://svn.apache.org/r1461617
Log:
[CXF-4929] Minor updates to get server response filters work better with
generic entities and annotations
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ContainerResponseContextImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/AbstractResponseContextImpl.java
Wed Mar 27 14:46:58 2013
@@ -35,6 +35,7 @@ import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.StatusType;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.message.Message;
@@ -60,7 +61,7 @@ public abstract class AbstractResponseCo
}
public Object getEntity() {
- return r.getEntity();
+ return InjectionUtils.getEntity(r.getEntity());
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ContainerResponseContextImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ContainerResponseContextImpl.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ContainerResponseContextImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ContainerResponseContextImpl.java
Wed Mar 27 14:46:58 2013
@@ -27,20 +27,19 @@ import javax.ws.rs.container.ContainerRe
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
-import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.message.Message;
public class ContainerResponseContextImpl extends AbstractResponseContextImpl
implements ContainerResponseContext {
- private OperationResourceInfo ori;
+ private Method invoked;
public ContainerResponseContextImpl(Response r,
Message m,
- OperationResourceInfo ori) {
+ Method invoked) {
super(r, m);
- this.ori = ori;
+ this.invoked = invoked;
}
@Override
@@ -55,13 +54,9 @@ public class ContainerResponseContextImp
@Override
public Type getEntityType() {
- Method invoked = ori == null ? null : ori.getAnnotatedMethod() != null
- ? ori.getAnnotatedMethod() : ori.getMethodToInvoke();
-
return InjectionUtils.getGenericResponseType(invoked,
super.r.getEntity(),
getEntityClass(),
- ori,
super.m.getExchange());
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
Wed Mar 27 14:46:58 2013
@@ -144,8 +144,7 @@ public final class ResponseImpl extends
return headers;
}
- // TODO: Make this method private with the upgrade to the latest API
snapshot
- public String getHeader(String header) {
+ private String getHeader(String header) {
Object value = metadata.getFirst(header);
return value == null ? null : value.toString();
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
Wed Mar 27 14:46:58 2013
@@ -35,7 +35,6 @@ import java.util.logging.Logger;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.container.AsyncResponse;
-import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@@ -162,7 +161,16 @@ public class JAXRSOutInterceptor extends
Method invoked = ori == null ? null : ori.getAnnotatedMethod() != null
? ori.getAnnotatedMethod() : ori.getMethodToInvoke();
- Annotation[] annotations = invoked != null ? invoked.getAnnotations()
: new Annotation[]{};
+ Annotation[] annotations = null;
+ Annotation[] staticAnns = invoked != null ? invoked.getAnnotations() :
new Annotation[]{};
+ Annotation[] responseAnns =
((ResponseImpl)response).getEntityAnnotations();
+ if (responseAnns != null) {
+ annotations = new Annotation[staticAnns.length +
responseAnns.length];
+ System.arraycopy(staticAnns, 0, annotations, 0, staticAnns.length);
+ System.arraycopy(responseAnns, 0, annotations, staticAnns.length,
responseAnns.length);
+ } else {
+ annotations = staticAnns;
+ }
((ResponseImpl)response).setStatus(
getActualStatus(response.getStatus(), entity));
@@ -187,7 +195,7 @@ public class JAXRSOutInterceptor extends
// Run the filters
try {
- JAXRSUtils.runContainerResponseFilters(providerFactory, response,
message, ori);
+ JAXRSUtils.runContainerResponseFilters(providerFactory, response,
message, ori, invoked);
} catch (IOException ex) {
handleWriteException(providerFactory, message, ex, firstTry);
return;
@@ -197,7 +205,7 @@ public class JAXRSOutInterceptor extends
}
// Write the entity
- entity = getEntity(response.getEntity());
+ entity = InjectionUtils.getEntity(response.getEntity());
setResponseStatus(message, getActualStatus(response.getStatus(),
entity));
if (entity == null) {
responseHeaders.putSingle(HttpHeaders.CONTENT_LENGTH, "0");
@@ -220,7 +228,7 @@ public class JAXRSOutInterceptor extends
Class<?> targetType = InjectionUtils.getRawResponseClass(entity);
Type genericType =
- InjectionUtils.getGenericResponseType(invoked,
response.getEntity(), targetType, ori, exchange);
+ InjectionUtils.getGenericResponseType(invoked,
response.getEntity(), targetType, exchange);
annotations = ((ResponseImpl)response).getEntityAnnotations();
List<WriterInterceptor> writers = providerFactory
@@ -281,14 +289,6 @@ public class JAXRSOutInterceptor extends
}
}
- private Object getEntity(Object o) {
- if (o != null) {
- return GenericEntity.class.isAssignableFrom(o.getClass()) ?
((GenericEntity<?>)o).getEntity() : o;
- } else {
- return o;
- }
- }
-
private boolean checkBufferingMode(Message m, List<WriterInterceptor>
writers, boolean firstTry) {
if (!firstTry) {
return false;
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
Wed Mar 27 14:46:58 2013
@@ -55,7 +55,6 @@ import javax.ws.rs.ClientErrorException;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
@@ -93,7 +92,6 @@ import org.apache.cxf.jaxrs.impl.tl.Thre
import org.apache.cxf.jaxrs.impl.tl.ThreadLocalSecurityContext;
import org.apache.cxf.jaxrs.impl.tl.ThreadLocalUriInfo;
import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
-import org.apache.cxf.jaxrs.model.OperationResourceInfo;
import org.apache.cxf.jaxrs.model.Parameter;
import org.apache.cxf.jaxrs.model.ParameterType;
import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
@@ -1174,7 +1172,6 @@ public final class InjectionUtils {
public static Type getGenericResponseType(Method invoked,
Object targetObject,
Class<?> targetType,
- OperationResourceInfo ori,
Exchange exchange) {
if (targetObject == null) {
return null;
@@ -1183,8 +1180,7 @@ public final class InjectionUtils {
if (GenericEntity.class.isAssignableFrom(targetObject.getClass())) {
type = ((GenericEntity<?>)targetObject).getType();
} else if (invoked == null
- || !invoked.getReturnType().isAssignableFrom(targetType)
- || exchange.get(AsyncResponse.class) != null) {
+ || !invoked.getReturnType().isAssignableFrom(targetType)) {
// when a method has been invoked it is still possible that either
an ExceptionMapper
// or a ResponseHandler filter overrides a response entity; if it
happens then
// the Type is the class of the response object, unless this new
entity is assignable
@@ -1193,11 +1189,15 @@ public final class InjectionUtils {
} else {
type = invoked.getGenericReturnType();
if (type instanceof TypeVariable) {
- type =
InjectionUtils.getSuperType(ori.getClassResourceInfo().getServiceClass(),
-
(TypeVariable<?>)type);
+ type =
InjectionUtils.getSuperType(invoked.getDeclaringClass(),
+ (TypeVariable<?>)type);
}
}
return type;
}
+
+ public static Object getEntity(Object o) {
+ return o instanceof GenericEntity ? ((GenericEntity<?>)o).getEntity()
: o;
+ }
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
Wed Mar 27 14:46:58 2013
@@ -1574,7 +1574,8 @@ public final class JAXRSUtils {
public static void runContainerResponseFilters(ServerProviderFactory pf,
Response r,
Message m,
- OperationResourceInfo ori)
throws IOException, Throwable {
+ OperationResourceInfo ori,
+ Method invoked) throws
IOException, Throwable {
List<ProviderInfo<ContainerResponseFilter>> containerFilters =
pf.getContainerResponseFilters(ori == null ? null :
ori.getNameBindings());
if (!containerFilters.isEmpty()) {
@@ -1583,7 +1584,7 @@ public final class JAXRSUtils {
false,
true);
ContainerResponseContext responseContext =
- new ContainerResponseContextImpl(r, m, ori);
+ new ContainerResponseContextImpl(r, m, invoked);
for (ProviderInfo<ContainerResponseFilter> filter :
containerFilters) {
InjectionUtils.injectContexts(filter.getProvider(), filter, m);
filter.getProvider().filter(requestContext, responseContext);
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
Wed Mar 27 14:46:58 2013
@@ -77,7 +77,7 @@ public class ResponseImplTest extends As
ResponseImpl ri = new ResponseImpl(200);
MetadataMap<String, Object> meta = new MetadataMap<String, Object>();
ri.addMetadata(meta);
- assertNull(ri.getHeader("a"));
+ assertNull(ri.getHeaderString("a"));
meta.putSingle("a", "aValue");
assertEquals("aValue", ri.getHeaderString("a"));
meta.add("a", "aValue2");
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
Wed Mar 27 14:46:58 2013
@@ -22,10 +22,12 @@ package org.apache.cxf.systest.jaxrs;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
@@ -54,6 +56,7 @@ import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
public class BookServer20 extends AbstractBusTestServerBase {
@@ -81,6 +84,7 @@ public class BookServer20 extends Abstra
providers.add(new PostMatchContainerRequestFilter());
providers.add(new FaultyContainerRequestFilter());
providers.add(new PreMatchReplaceStreamOrAddress());
+ providers.add(new GenericHandlerWriter());
sf.setProviders(providers);
sf.setResourceProvider(BookStore.class,
new SingletonResourceProvider(new BookStore(),
true));
@@ -218,6 +222,8 @@ public class BookServer20 extends Abstra
@Priority(3)
public static class PostMatchContainerResponseFilter implements
ContainerResponseFilter {
+ @Context
+ private ResourceInfo rInfo;
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws
IOException {
@@ -229,7 +235,19 @@ public class BookServer20 extends Abstra
responseContext.getHeaders().putSingle("FilterException",
requestContext.getProperty("filterexception"));
}
- ct += ";charset=";
+ Object entity = responseContext.getEntity();
+ Type entityType = responseContext.getEntityType();
+ if (entity instanceof GenericHandler &&
InjectionUtils.getActualType(entityType) == Book.class) {
+ ct += ";charset=ISO-8859-1";
+ if
("getGenericBook2".equals(rInfo.getResourceMethod().getName())) {
+ Annotation[] anns = responseContext.getEntityAnnotations();
+ if (anns.length == 4 && anns[3].annotationType() ==
Context.class) {
+ responseContext.getHeaders().addFirst("Annotations",
"OK");
+ }
+ }
+ } else {
+ ct += ";charset=";
+ }
responseContext.getHeaders().putSingle("Content-Type", ct);
responseContext.getHeaders().add("Response", "OK");
}
@@ -328,7 +346,9 @@ public class BookServer20 extends Abstra
public void aroundWriteTo(WriterInterceptorContext context) throws
IOException, WebApplicationException {
context.getHeaders().add("ServerWriterInterceptor", "serverWrite");
String ct =
context.getHeaders().getFirst("Content-Type").toString();
- ct += "us-ascii";
+ if (!ct.endsWith("ISO-8859-1")) {
+ ct += "us-ascii";
+ }
context.getHeaders().putSingle("Content-Type", ct);
context.proceed();
}
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
Wed Mar 27 14:46:58 2013
@@ -23,6 +23,7 @@ package org.apache.cxf.systest.jaxrs;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.URI;
@@ -645,6 +646,14 @@ public class BookStore {
}
@GET
+ @Path("/genericbooks2/{bookId}/")
+ @Produces("application/xml")
+ public Response getGenericBook2(@PathParam("bookId") String id)
+ throws BookNotFoundFault {
+ return Response.ok().entity(getGenericBook(id),
getExtraAnnotations()).build();
+ }
+
+ @GET
@Path("/genericresponse/{bookId}/")
@Produces("application/xml")
public Response getGenericResponseBook(@PathParam("bookId") String id)
@@ -1393,6 +1402,15 @@ public class BookStore {
}
}
+
+ private Annotation[] getExtraAnnotations() {
+ try {
+ Method m = BookBean.class.getMethod("setUriInfo", new
Class[]{UriInfo.class});
+ return m.getAnnotations();
+ } catch (Throwable ex) {
+ throw new RuntimeException(ex);
+ }
+ }
}
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java?rev=1461617&r1=1461616&r2=1461617&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
Wed Mar 27 14:46:58 2013
@@ -59,6 +59,33 @@ public class JAXRS20ClientServerBookTest
}
@Test
+ public void testGetGenericBook() throws Exception {
+ String address = "http://localhost:" + PORT +
"/bookstore/genericbooks/123";
+ doTestGetGenericBook(address, false);
+ }
+
+ @Test
+ public void testGetGenericBook2() throws Exception {
+ String address = "http://localhost:" + PORT +
"/bookstore/genericbooks2/123";
+ doTestGetGenericBook(address, true);
+ }
+
+ private void doTestGetGenericBook(String address, boolean
checkAnnotations) throws Exception {
+ WebClient wc = WebClient.create(address);
+
WebClient.getConfig(wc).getHttpConduit().getClient().setReceiveTimeout(1000000L);
+ wc.accept("application/xml");
+ Book book = wc.get(Book.class);
+ assertEquals(123L, book.getId());
+ MediaType mt = wc.getResponse().getMediaType();
+ assertEquals("application/xml;charset=ISO-8859-1", mt.toString());
+ if (checkAnnotations) {
+ assertEquals("OK",
wc.getResponse().getHeaderString("Annotations"));
+ } else {
+ assertNull(wc.getResponse().getHeaderString("Annotations"));
+ }
+ }
+
+ @Test
public void testGetBook() {
String address = "http://localhost:" + PORT +
"/bookstore/bookheaders/simple";
doTestGetBook(address);