Author: sergeyb
Date: Tue Apr 2 15:06:29 2013
New Revision: 1463583
URL: http://svn.apache.org/r1463583
Log:
[CXF-4825] Trying to make sure JAX-RS Responses created by alternative
implementations are not used internally or replaced by the CXF implementation
if needed
Added:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
(with props)
Modified:
cxf/trunk/api/src/main/java/org/apache/cxf/common/util/ReflectionUtil.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/impl/WebApplicationExceptionMapper.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/JAXRSUtils.java
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.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/JAXRSClientServerBookTest.java
Modified:
cxf/trunk/api/src/main/java/org/apache/cxf/common/util/ReflectionUtil.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/api/src/main/java/org/apache/cxf/common/util/ReflectionUtil.java?rev=1463583&r1=1463582&r2=1463583&view=diff
==============================================================================
--- cxf/trunk/api/src/main/java/org/apache/cxf/common/util/ReflectionUtil.java
(original)
+++ cxf/trunk/api/src/main/java/org/apache/cxf/common/util/ReflectionUtil.java
Tue Apr 2 15:06:29 2013
@@ -46,6 +46,23 @@ public final class ReflectionUtil {
// intentionally empty
}
+ public static <T> T accessDeclaredField(final Field f, final Object o,
final Class<T> responseClass) {
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ try {
+ f.setAccessible(true);
+ return responseClass.cast(f.get(o));
+ } catch (SecurityException e) {
+ return null;
+ } catch (IllegalAccessException e) {
+ return null;
+ } finally {
+ f.setAccessible(false);
+ }
+ }
+ });
+ }
+
public static Field getDeclaredField(final Class<?> cls, final String
name) {
return AccessController.doPrivileged(new PrivilegedAction<Field>() {
public Field run() {
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=1463583&r1=1463582&r2=1463583&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
Tue Apr 2 15:06:29 2013
@@ -85,6 +85,10 @@ public final class ResponseImpl extends
this.entityAnnotations = anns;
}
+ public void setEntityAnnotations(Annotation[] anns) {
+ this.entityAnnotations = anns;
+ }
+
public Annotation[] getEntityAnnotations() {
return entityAnnotations;
}
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WebApplicationExceptionMapper.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WebApplicationExceptionMapper.java?rev=1463583&r1=1463582&r2=1463583&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WebApplicationExceptionMapper.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WebApplicationExceptionMapper.java
Tue Apr 2 15:06:29 2013
@@ -23,12 +23,14 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
+
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.logging.FaultListener;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.PhaseInterceptorChain;
@@ -72,7 +74,8 @@ public class WebApplicationExceptionMapp
}
if (doAddMessage) {
- r =
Response.fromResponse(r).entity(errorMessage).type(MediaType.TEXT_PLAIN).build();
+ r = JAXRSUtils.copyResponseIfNeeded(r);
+ r =
JAXRSUtils.fromResponse(r).entity(errorMessage).type(MediaType.TEXT_PLAIN).build();
}
return r;
}
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=1463583&r1=1463582&r2=1463583&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
Tue Apr 2 15:06:29 2013
@@ -147,6 +147,8 @@ public class JAXRSOutInterceptor extends
OperationResourceInfo ori,
boolean firstTry) {
+ response = JAXRSUtils.copyResponseIfNeeded(response);
+
final Exchange exchange = message.getExchange();
Object entity = response.getEntity();
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=1463583&r1=1463582&r2=1463583&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
Tue Apr 2 15:06:29 2013
@@ -98,6 +98,7 @@ import org.apache.cxf.common.classloader
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.PackageUtils;
+import org.apache.cxf.common.util.ReflectionUtil;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.jaxrs.JAXRSServiceImpl;
@@ -120,6 +121,8 @@ import org.apache.cxf.jaxrs.impl.ReaderI
import org.apache.cxf.jaxrs.impl.RequestImpl;
import org.apache.cxf.jaxrs.impl.ResourceContextImpl;
import org.apache.cxf.jaxrs.impl.ResourceInfoImpl;
+import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl;
+import org.apache.cxf.jaxrs.impl.ResponseImpl;
import org.apache.cxf.jaxrs.impl.SecurityContextImpl;
import org.apache.cxf.jaxrs.impl.UriInfoImpl;
import org.apache.cxf.jaxrs.impl.WriterInterceptorContextImpl;
@@ -1592,6 +1595,57 @@ public final class JAXRSUtils {
}
}
+ public static Response toResponse(int status) {
+ return toResponseBuilder(status).build();
+ }
+
+ public static Response toResponse(Response.Status status) {
+ return toResponse(status.getStatusCode());
+ }
+
+ public static ResponseBuilder toResponseBuilder(int status) {
+ return new ResponseBuilderImpl().status(status);
+ }
+
+ public static ResponseBuilder toResponseBuilder(Response.Status status) {
+ return toResponseBuilder(status.getStatusCode());
+ }
+
+ public static ResponseBuilder fromResponse(Response response) {
+ ResponseBuilder rb = toResponseBuilder(response.getStatus());
+ rb.entity(response.getEntity());
+ for (Map.Entry<String, List<Object>> entry :
response.getHeaders().entrySet()) {
+ List<Object> values = entry.getValue();
+ for (Object value : values) {
+ rb.header(entry.getKey(), value);
+ }
+ }
+ return rb;
+ }
+
+ public static Response copyResponseIfNeeded(Response response) {
+ if (!(response instanceof ResponseImpl)) {
+ Response r = fromResponse(response).build();
+ Field[] declaredFields =
ReflectionUtil.getDeclaredFields(response.getClass());
+ for (Field f : declaredFields) {
+ Class<?> declClass = f.getType();
+ if (declClass == Annotation[].class) {
+ try {
+ Annotation[] fieldAnnotations =
+ ReflectionUtil.accessDeclaredField(f, response,
Annotation[].class);
+
((ResponseImpl)r).setEntityAnnotations(fieldAnnotations);
+ } catch (Throwable ex) {
+ LOG.warning("Custom annotations if any may can not be
copied");
+ }
+ break;
+ }
+ }
+ return r;
+ } else {
+ return response;
+ }
+ }
+
public static Message getCurrentMessage() {
return PhaseInterceptorChain.getCurrentMessage();
}
Modified:
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=1463583&r1=1463582&r2=1463583&view=diff
==============================================================================
---
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
(original)
+++
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
Tue Apr 2 15:06:29 2013
@@ -324,11 +324,11 @@ public abstract class AbstractClient imp
protected ResponseBuilder setResponseBuilder(Message outMessage, Exchange
exchange) throws Exception {
Response response = exchange.get(Response.class);
if (response != null) {
- return Response.fromResponse(response);
+ return
JAXRSUtils.fromResponse(JAXRSUtils.copyResponseIfNeeded(response));
}
Integer status = getResponseCode(exchange);
- ResponseBuilder currentResponseBuilder = Response.status(status);
+ ResponseBuilder currentResponseBuilder =
JAXRSUtils.toResponseBuilder(status);
Message responseMessage = exchange.getInMessage() != null
? exchange.getInMessage() : exchange.getInFaultMessage();
Modified:
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java?rev=1463583&r1=1463582&r2=1463583&view=diff
==============================================================================
---
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
(original)
+++
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
Tue Apr 2 15:06:29 2013
@@ -1070,7 +1070,7 @@ public class WebClient extends AbstractC
entity = currentResponse.getEntity();
}
}
- rb = Response.fromResponse(currentResponse);
+ rb = JAXRSUtils.fromResponse(currentResponse);
rb.entity(entity instanceof Response
? ((Response)entity).getEntity() : entity);
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=1463583&r1=1463582&r2=1463583&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
Tue Apr 2 15:06:29 2013
@@ -1148,6 +1148,14 @@ public class BookStore {
return this;
}
+ @Path("/customresponse")
+ @GET
+ @Produces("application/xml")
+ public Response getCustomBook() {
+ return new CustomResponse(
+ Response.ok().entity(new Book("Book",
222L)).header("customresponse", "OK").build());
+ }
+
@POST
@Path("/booksecho2")
@Consumes("text/plain")
Added:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java?rev=1463583&view=auto
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
(added)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
Tue Apr 2 15:06:29 2013
@@ -0,0 +1,168 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.systest.jaxrs;
+
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.Link.Builder;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+
+public class CustomResponse extends Response {
+ private Response r;
+ public CustomResponse(Response r) {
+ this.r = r;
+ }
+ @Override
+ public boolean bufferEntity() {
+ return false;
+ }
+ @Override
+ public void close() {
+ // TODO Auto-generated method stub
+
+ }
+ @Override
+ public Set<String> getAllowedMethods() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Map<String, NewCookie> getCookies() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Date getDate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Object getEntity() {
+ return r.getEntity();
+ }
+ @Override
+ public EntityTag getEntityTag() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public String getHeaderString(String arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Locale getLanguage() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Date getLastModified() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public int getLength() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+ @Override
+ public Link getLink(String arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Builder getLinkBuilder(String arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public Set<Link> getLinks() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public URI getLocation() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public MediaType getMediaType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public MultivaluedMap<String, Object> getMetadata() {
+ return r.getMetadata();
+ }
+ @Override
+ public int getStatus() {
+ return r.getStatus();
+ }
+ @Override
+ public StatusType getStatusInfo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public MultivaluedMap<String, String> getStringHeaders() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public boolean hasEntity() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ @Override
+ public boolean hasLink(String arg0) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ @Override
+ public <T> T readEntity(Class<T> arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <T> T readEntity(GenericType<T> arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <T> T readEntity(Class<T> arg0, Annotation[] arg1) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ @Override
+ public <T> T readEntity(GenericType<T> arg0, Annotation[] arg1) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomResponse.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java?rev=1463583&r1=1463582&r2=1463583&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerBookTest.java
Tue Apr 2 15:06:29 2013
@@ -91,6 +91,16 @@ public class JAXRSClientServerBookTest e
}
+
+ @Test
+ public void testGetCustomBookResponse() {
+ String address = "http://localhost:" + PORT +
"/bookstore/customresponse";
+ WebClient wc = WebClient.create(address);
+ Response r = wc.accept("application/xml").get(Response.class);
+ Book book = r.readEntity(Book.class);
+ assertEquals(222L, book.getId());
+ assertEquals("OK", r.getHeaderString("customresponse"));
+ }
@Test
public void testGetCustomBookText() {