You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2010/02/12 15:45:23 UTC
svn commit: r909435 - in /cxf/branches/2.2.x-fixes: ./
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/
rt/frontend/jaxrs/src/main/resources/schemas/ systests/jaxrs/src/test/java...
Author: sergeyb
Date: Fri Feb 12 14:45:22 2010
New Revision: 909435
URL: http://svn.apache.org/viewvc?rev=909435&view=rev
Log:
Merged revisions 909102 via svnmerge from
https://svn.apache.org/repos/asf/cxf/trunk
........
r909102 | sergeyb | 2010-02-11 18:41:34 +0000 (Thu, 11 Feb 2010) | 1 line
JAXRS : making proxies and webclients optionally thread-safe
........
Added:
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientState.java
- copied unchanged from r909102, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientState.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/LocalClientState.java
- copied unchanged from r909102, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/LocalClientState.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ThreadLocalClientState.java
- copied unchanged from r909102, cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ThreadLocalClientState.java
cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultithreadedClientTest.java
- copied unchanged from r909102, cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultithreadedClientTest.java
Modified:
cxf/branches/2.2.x-fixes/ (props changed)
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java
cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
Propchange: cxf/branches/2.2.x-fixes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Feb 12 14:45:22 2010
@@ -1 +1 @@
-/cxf/trunk:908451
+/cxf/trunk:908451,909102
Propchange: cxf/branches/2.2.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java Fri Feb 12 14:45:22 2010
@@ -83,16 +83,14 @@
private static final String RESPONSE_CONTEXT = "ResponseContext";
protected ClientConfiguration cfg = new ClientConfiguration();
+ private ClientState state;
- private MultivaluedMap<String, String> requestHeaders = new MetadataMap<String, String>();
- private ResponseBuilder responseBuilder;
+ protected AbstractClient(URI baseURI) {
+ this.state = new LocalClientState(baseURI);
+ }
- private URI baseURI;
- private UriBuilder currentBuilder;
-
- protected AbstractClient(URI baseURI, URI currentURI) {
- this.baseURI = baseURI;
- this.currentBuilder = new UriBuilderImpl(currentURI);
+ protected AbstractClient(ClientState initialState) {
+ this.state = initialState;
}
/**
@@ -102,20 +100,25 @@
if (values == null) {
throw new IllegalArgumentException();
}
- if (HttpHeaders.CONTENT_TYPE.equals(name) && values.length > 1) {
- throw new WebApplicationException();
- }
- for (Object o : values) {
- requestHeaders.add(name, o.toString());
+ if (HttpHeaders.CONTENT_TYPE.equals(name)) {
+ if (values.length > 1) {
+ throw new IllegalArgumentException("Content-Type can have a single value only");
+ }
+ type(values[0].toString());
+ } else {
+ for (Object o : values) {
+ possiblyAddHeader(name, o.toString());
+ }
}
return this;
}
+
/**
* {@inheritDoc}
*/
public Client headers(MultivaluedMap<String, String> map) {
- requestHeaders.putAll(map);
+ state.getRequestHeaders().putAll(map);
return this;
}
@@ -124,7 +127,7 @@
*/
public Client accept(MediaType... types) {
for (MediaType mt : types) {
- requestHeaders.add(HttpHeaders.ACCEPT, mt.toString());
+ possiblyAddHeader(HttpHeaders.ACCEPT, mt.toString());
}
return this;
}
@@ -140,7 +143,7 @@
* {@inheritDoc}
*/
public Client type(String type) {
- requestHeaders.putSingle(HttpHeaders.CONTENT_TYPE, type);
+ state.getRequestHeaders().putSingle(HttpHeaders.CONTENT_TYPE, type);
return this;
}
@@ -149,7 +152,7 @@
*/
public Client accept(String... types) {
for (String type : types) {
- requestHeaders.add(HttpHeaders.ACCEPT, type);
+ possiblyAddHeader(HttpHeaders.ACCEPT, type);
}
return this;
}
@@ -158,7 +161,7 @@
* {@inheritDoc}
*/
public Client cookie(Cookie cookie) {
- requestHeaders.add(HttpHeaders.COOKIE, cookie.toString());
+ possiblyAddHeader(HttpHeaders.COOKIE, cookie.toString());
return this;
}
@@ -168,7 +171,7 @@
public Client modified(Date date, boolean ifNot) {
SimpleDateFormat dateFormat = HttpUtils.getHttpDateFormat();
String hName = ifNot ? HttpHeaders.IF_UNMODIFIED_SINCE : HttpHeaders.IF_MODIFIED_SINCE;
- requestHeaders.putSingle(hName, dateFormat.format(date));
+ state.getRequestHeaders().putSingle(hName, dateFormat.format(date));
return this;
}
@@ -176,7 +179,7 @@
* {@inheritDoc}
*/
public Client language(String language) {
- requestHeaders.putSingle(HttpHeaders.CONTENT_LANGUAGE, language);
+ state.getRequestHeaders().putSingle(HttpHeaders.CONTENT_LANGUAGE, language);
return this;
}
@@ -185,7 +188,7 @@
*/
public Client match(EntityTag tag, boolean ifNot) {
String hName = ifNot ? HttpHeaders.IF_NONE_MATCH : HttpHeaders.IF_MATCH;
- requestHeaders.putSingle(hName, tag.toString());
+ state.getRequestHeaders().putSingle(hName, tag.toString());
return this;
}
@@ -194,7 +197,7 @@
*/
public Client acceptLanguage(String... languages) {
for (String s : languages) {
- requestHeaders.add(HttpHeaders.ACCEPT_LANGUAGE, s);
+ possiblyAddHeader(HttpHeaders.ACCEPT_LANGUAGE, s);
}
return this;
}
@@ -204,7 +207,7 @@
*/
public Client acceptEncoding(String... encs) {
for (String s : encs) {
- requestHeaders.add(HttpHeaders.ACCEPT_ENCODING, s);
+ possiblyAddHeader(HttpHeaders.ACCEPT_ENCODING, s);
}
return this;
}
@@ -213,7 +216,7 @@
* {@inheritDoc}
*/
public Client encoding(String enc) {
- requestHeaders.putSingle(HttpHeaders.CONTENT_ENCODING, enc);
+ state.getRequestHeaders().putSingle(HttpHeaders.CONTENT_ENCODING, enc);
return this;
}
@@ -222,7 +225,7 @@
*/
public MultivaluedMap<String, String> getHeaders() {
MultivaluedMap<String, String> map = new MetadataMap<String, String>();
- map.putAll(requestHeaders);
+ map.putAll(state.getRequestHeaders());
return map;
}
@@ -230,7 +233,7 @@
* {@inheritDoc}
*/
public URI getBaseURI() {
- return baseURI;
+ return state.getBaseURI();
}
/**
@@ -244,37 +247,50 @@
* {@inheritDoc}
*/
public Response getResponse() {
- if (responseBuilder == null) {
+ if (state.getResponseBuilder() == null) {
return null;
}
- return responseBuilder.build();
+ return state.getResponseBuilder().build();
}
/**
* {@inheritDoc}
*/
public Client reset() {
- requestHeaders.clear();
- resetResponse();
+ state.reset();
return this;
}
+ private void possiblyAddHeader(String name, String value) {
+ if (!isDuplicate(name, value)) {
+ state.getRequestHeaders().add(name, value);
+ }
+ }
+
+ private boolean isDuplicate(String name, String value) {
+ List<String> values = state.getRequestHeaders().get(name);
+ return values != null && values.contains(value) ? true : false;
+ }
+
+ protected ClientState getState() {
+ return state;
+ }
protected UriBuilder getCurrentBuilder() {
- return currentBuilder;
+ return state.getCurrentBuilder();
}
protected void resetResponse() {
- responseBuilder = null;
+ state.setResponseBuilder(null);
}
protected void resetBaseAddress(URI uri) {
- baseURI = uri;
+ state.setBaseURI(uri);
resetCurrentBuilder(uri);
}
protected void resetCurrentBuilder(URI uri) {
- currentBuilder = new UriBuilderImpl(uri);
+ state.setCurrentBuilder(new UriBuilderImpl(uri));
}
protected ResponseBuilder setResponseBuilder(HttpURLConnection conn, Exchange exchange) throws Throwable {
@@ -297,19 +313,20 @@
}
}
int status = responseCode.intValue();
- responseBuilder = Response.status(status);
+ ResponseBuilder currentResponseBuilder = Response.status(status);
+
for (Map.Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {
if (null == entry.getKey()) {
continue;
}
if (HttpUtils.isDateRelatedHeader(entry.getKey())) {
- responseBuilder.header(entry.getKey(), entry.getValue());
+ currentResponseBuilder.header(entry.getKey(), entry.getValue());
} else if (entry.getValue().size() > 0) {
String[] values = entry.getValue().get(0).split(",");
for (String s : values) {
String theValue = s.trim();
if (theValue.length() > 0) {
- responseBuilder.header(entry.getKey(), theValue);
+ currentResponseBuilder.header(entry.getKey(), theValue);
}
}
}
@@ -321,19 +338,21 @@
if (status >= 400) {
try {
InputStream errorStream = mStream == null ? conn.getErrorStream() : mStream;
- responseBuilder.entity(errorStream);
+ currentResponseBuilder.entity(errorStream);
} catch (Exception ex) {
// nothing we can do really
}
} else {
try {
InputStream stream = mStream == null ? conn.getInputStream() : mStream;
- responseBuilder.entity(stream);
+ currentResponseBuilder.entity(stream);
} catch (Exception ex) {
// it may that the successful response has no response body
}
}
- return responseBuilder;
+ ResponseBuilder rb = currentResponseBuilder.clone();
+ state.setResponseBuilder(currentResponseBuilder);
+ return rb;
}
@SuppressWarnings("unchecked")
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ClientProxyImpl.java Fri Feb 12 14:45:22 2010
@@ -76,9 +76,18 @@
private boolean isRoot;
private Map<String, Object> valuesMap;
- public ClientProxyImpl(URI baseURI, URI currentURI, ClassResourceInfo cri, boolean isRoot,
+ public ClientProxyImpl(URI baseURI, ClassResourceInfo cri, boolean isRoot,
boolean inheritHeaders, Object... varValues) {
- super(baseURI, currentURI);
+ super(baseURI);
+ this.cri = cri;
+ this.isRoot = isRoot;
+ this.inheritHeaders = inheritHeaders;
+ initValuesMap(varValues);
+ }
+
+ public ClientProxyImpl(ClientState initialState, ClassResourceInfo cri, boolean isRoot,
+ boolean inheritHeaders, Object... varValues) {
+ super(initialState);
this.cri = cri;
this.isRoot = isRoot;
this.inheritHeaders = inheritHeaders;
@@ -148,15 +157,16 @@
if (subCri == null) {
reportInvalidResourceMethod(m, "INVALID_SUBRESOURCE");
}
- ClientProxyImpl proxyImpl = new ClientProxyImpl(getBaseURI(), uri, subCri, false, inheritHeaders);
- proxyImpl.setConfiguration(getConfiguration());
- Object proxy = JAXRSClientFactory.create(m.getReturnType(), proxyImpl);
+ MultivaluedMap<String, String> subHeaders = paramHeaders;
if (inheritHeaders) {
- WebClient.client(proxy).headers(headers);
+ subHeaders.putAll(headers);
}
- WebClient.client(proxy).headers(paramHeaders);
- return proxy;
+
+ ClientState newState = getState().newState(uri, headers);
+ ClientProxyImpl proxyImpl = new ClientProxyImpl(newState, subCri, false, inheritHeaders);
+ proxyImpl.setConfiguration(getConfiguration());
+ return JAXRSClientFactory.create(m.getReturnType(), proxyImpl);
}
headers.putAll(paramHeaders);
@@ -443,7 +453,7 @@
protected Object handleResponse(HttpURLConnection connect, Message outMessage, OperationResourceInfo ori)
throws Throwable {
- Response r = setResponseBuilder(connect, outMessage.getExchange()).clone().build();
+ Response r = setResponseBuilder(connect, outMessage.getExchange()).build();
Method method = ori.getMethodToInvoke();
checkResponse(method, r, outMessage);
if (method.getReturnType() == Void.class) {
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactory.java Fri Feb 12 14:45:22 2010
@@ -23,6 +23,8 @@
import java.util.Collections;
import java.util.List;
+import javax.ws.rs.core.MultivaluedMap;
+
import org.apache.cxf.common.util.ProxyHelper;
import org.apache.cxf.jaxrs.model.UserResource;
@@ -113,6 +115,23 @@
}
/**
+ * Creates a thread safe proxy
+ * @param baseAddress baseAddress
+ * @param cls proxy class, if not interface then a CGLIB proxy will be created
+ * @param providers list of providers
+ * @param threadSafe if true then a thread-safe proxy will be created
+ * @return typed proxy
+ */
+ public static <T> T create(String baseAddress, Class<T> cls, List<?> providers, boolean threadSafe) {
+ JAXRSClientFactoryBean bean = getBean(baseAddress, cls, null);
+ bean.setProviders(providers);
+ if (threadSafe) {
+ bean.setInitialState(new ThreadLocalClientState(baseAddress));
+ }
+ return bean.create(cls);
+ }
+
+ /**
* Creates a proxy
* @param baseAddress baseAddress
* @param cls proxy class, if not interface then a CGLIB proxy will be created
@@ -172,6 +191,26 @@
}
/**
+ * Creates a thread safe proxy using user resource model
+ * @param baseAddress baseAddress
+ * @param cls proxy class, if not interface then a CGLIB proxy will be created
+ * @param modelRef model location
+ * @param providers list of providers
+ * @param threadSafe if true then thread-safe proxy will be created
+ * @return typed proxy
+ */
+ public static <T> T createFromModel(String baseAddress, Class<T> cls, String modelRef,
+ List<?> providers, boolean threadSafe) {
+ JAXRSClientFactoryBean bean = WebClient.getBean(baseAddress, null);
+ bean.setProviders(providers);
+ bean.setModelRef(modelRef);
+ if (threadSafe) {
+ bean.setInitialState(new ThreadLocalClientState(baseAddress));
+ }
+ return bean.create(cls);
+ }
+
+ /**
* Creates a proxy using user resource model
* @param baseAddress baseAddress
* @param cls proxy class, if not interface then a CGLIB proxy will be created
@@ -219,10 +258,21 @@
* @return typed proxy
*/
public static <T> T fromClient(Client client, Class<T> cls, boolean inheritHeaders) {
+ JAXRSClientFactoryBean bean = getBean(client.getCurrentURI().toString(), cls, null);
+ bean.setInheritHeaders(inheritHeaders);
+
+ ClientState clientState = WebClient.getClientState(client);
- T proxy = create(client.getCurrentURI(), cls, inheritHeaders);
- if (inheritHeaders) {
- WebClient.client(proxy).headers(client.getHeaders());
+ T proxy = null;
+ if (clientState == null) {
+ proxy = bean.create(cls);
+ if (inheritHeaders) {
+ WebClient.client(proxy).headers(client.getHeaders());
+ }
+ } else {
+ MultivaluedMap<String, String> headers = inheritHeaders ? client.getHeaders() : null;
+ bean.setInitialState(clientState.newState(client.getCurrentURI(), headers));
+ proxy = bean.create(cls);
}
WebClient.copyProperties(WebClient.client(proxy), client);
return proxy;
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/JAXRSClientFactoryBean.java Fri Feb 12 14:45:22 2010
@@ -46,6 +46,8 @@
private String password;
private boolean inheritHeaders;
private MultivaluedMap<String, String> headers;
+ private ClientState initialState;
+ private boolean threadSafe;
public JAXRSClientFactoryBean() {
this(new JAXRSServiceFactoryBean());
@@ -57,6 +59,10 @@
}
+ public void setThreadSafe(boolean threadSafe) {
+ this.threadSafe = threadSafe;
+ }
+
public String getUsername() {
return username;
}
@@ -108,8 +114,10 @@
try {
Endpoint ep = createEndpoint();
- WebClient client = new WebClient(getAddress());
- initClient(client, ep);
+ ClientState actualState = getActualState();
+ WebClient client = actualState == null ? new WebClient(getAddress())
+ : new WebClient(actualState);
+ initClient(client, ep, actualState == null);
return client;
} catch (Exception ex) {
@@ -118,6 +126,18 @@
}
}
+ private ClientState getActualState() {
+ if (threadSafe) {
+ initialState = new ThreadLocalClientState(getAddress());
+ }
+ if (initialState != null) {
+ return headers != null
+ ? initialState.newState(URI.create(getAddress()), headers) : initialState;
+ } else {
+ return null;
+ }
+ }
+
public <T> T create(Class<T> cls, Object... varValues) {
return cls.cast(createWithValues(varValues));
}
@@ -131,12 +151,18 @@
ClassResourceInfo cri = null;
try {
Endpoint ep = createEndpoint();
- URI baseURI = URI.create(getAddress());
cri = serviceFactory.getClassResourceInfo().get(0);
boolean isRoot = cri.getURITemplate() != null;
- ClientProxyImpl proxyImpl = new ClientProxyImpl(baseURI, baseURI, cri, isRoot, inheritHeaders,
- varValues);
- initClient(proxyImpl, ep);
+ ClientProxyImpl proxyImpl = null;
+ ClientState actualState = getActualState();
+ if (actualState == null) {
+ proxyImpl =
+ new ClientProxyImpl(URI.create(getAddress()), cri, isRoot, inheritHeaders, varValues);
+ } else {
+ proxyImpl =
+ new ClientProxyImpl(actualState, cri, isRoot, inheritHeaders, varValues);
+ }
+ initClient(proxyImpl, ep, actualState == null);
try {
return (Client)ProxyHelper.getProxy(cri.getServiceClass().getClassLoader(),
@@ -174,7 +200,7 @@
return cs;
}
- protected void initClient(AbstractClient client, Endpoint ep) {
+ protected void initClient(AbstractClient client, Endpoint ep, boolean addHeaders) {
if (username != null) {
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
@@ -188,9 +214,11 @@
client.getConfiguration().setBus(getBus());
client.getConfiguration().getOutInterceptors().addAll(getOutInterceptors());
client.getConfiguration().getInInterceptors().addAll(getInInterceptors());
- if (headers != null) {
+
+ if (headers != null && addHeaders) {
client.headers(headers);
}
+
setupFactory(ep);
}
@@ -201,4 +229,10 @@
}
}
}
+
+ public void setInitialState(ClientState initialState) {
+ this.initialState = initialState;
+ }
+
+
}
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java Fri Feb 12 14:45:22 2010
@@ -25,6 +25,7 @@
import java.net.HttpURLConnection;
import java.net.URI;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -40,7 +41,6 @@
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
-
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.helpers.CastUtils;
@@ -71,7 +71,11 @@
}
protected WebClient(URI baseAddress) {
- super(baseAddress, baseAddress);
+ super(baseAddress);
+ }
+
+ protected WebClient(ClientState state) {
+ super(state);
}
/**
@@ -95,6 +99,14 @@
/**
* Creates WebClient
* @param baseURI baseURI
+ */
+ public static WebClient create(String baseURI, boolean threadSafe) {
+ return create(baseURI, Collections.emptyList(), threadSafe);
+ }
+
+ /**
+ * Creates WebClient
+ * @param baseURI baseURI
* @param providers list of providers
*/
public static WebClient create(String baseAddress, List<?> providers) {
@@ -102,6 +114,20 @@
}
/**
+ * Creates WebClient
+ * @param baseURI baseURI
+ * @param providers list of providers
+ */
+ public static WebClient create(String baseAddress, List<?> providers, boolean threadSafe) {
+ JAXRSClientFactoryBean bean = getBean(baseAddress, null);
+ bean.setProviders(providers);
+ if (threadSafe) {
+ bean.setInitialState(new ThreadLocalClientState(baseAddress));
+ }
+ return bean.createWebClient();
+ }
+
+ /**
* Creates a Spring-configuration aware WebClient
* @param baseAddress baseAddress
* @param providers list of providers
@@ -159,9 +185,18 @@
* and subresource proxies if any
*/
public static WebClient fromClient(Client client, boolean inheritHeaders) {
- WebClient webClient = create(client.getCurrentURI());
- if (inheritHeaders) {
- webClient.headers(client.getHeaders());
+
+ WebClient webClient = null;
+
+ ClientState clientState = getClientState(client);
+ if (clientState == null) {
+ webClient = create(client.getCurrentURI());
+ if (inheritHeaders) {
+ webClient.headers(client.getHeaders());
+ }
+ } else {
+ MultivaluedMap<String, String> headers = inheritHeaders ? client.getHeaders() : null;
+ webClient = new WebClient(clientState.newState(client.getCurrentURI(), headers));
}
copyProperties(webClient, client);
return webClient;
@@ -586,7 +621,7 @@
protected Response handleResponse(HttpURLConnection conn, Message outMessage,
Class<?> responseClass, Type genericType) {
try {
- ResponseBuilder rb = setResponseBuilder(conn, outMessage.getExchange()).clone();
+ ResponseBuilder rb = setResponseBuilder(conn, outMessage.getExchange());
Response currentResponse = rb.clone().build();
Object entity = readBody(currentResponse, conn, outMessage, responseClass, genericType,
@@ -665,4 +700,15 @@
bean.setAddress(baseAddress);
return bean;
}
+
+ static ClientState getClientState(Client client) {
+ ClientState clientState = null;
+ if (client instanceof WebClient) {
+ clientState = ((AbstractClient)client).getState();
+ } else if (client instanceof InvocationHandlerAware) {
+ Object handler = ((InvocationHandlerAware)client).getInvocationHandler();
+ clientState = ((AbstractClient)handler).getState();
+ }
+ return clientState;
+ }
}
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/xml/XMLSource.java Fri Feb 12 14:45:22 2010
@@ -134,6 +134,18 @@
return value == null ? null : URI.create(value);
}
+ public URI[] getLinks(String expression, Map<String, String> namespaces) {
+ String[] values = getValues(expression, namespaces);
+ if (values == null) {
+ return null;
+ }
+ URI[] uris = new URI[values.length];
+ for (int i = 0; i < values.length; i++) {
+ uris[i] = URI.create(values[i]);
+ }
+ return uris;
+ }
+
public URI getBaseURI() {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("xml", XML_NAMESPACE);
Modified: cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd (original)
+++ cxf/branches/2.2.x-fixes/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd Fri Feb 12 14:45:22 2010
@@ -101,6 +101,7 @@
<xsd:attribute name="username" type="xsd:string"/>
<xsd:attribute name="password" type="xsd:string"/>
<xsd:attribute name="serviceName" type="xsd:QName"/>
+ <xsd:attribute name="threadSafe" type="xsd:boolean"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Modified: cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=909435&r1=909434&r2=909435&view=diff
==============================================================================
--- cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/branches/2.2.x-fixes/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Fri Feb 12 14:45:22 2010
@@ -633,6 +633,27 @@
return new Long(theBookId);
}
+ @POST
+ @Path("/booksecho")
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public Response echoBookNameAndHeader(@HeaderParam("CustomHeader") String headerValue, String name) {
+ return Response.ok().entity(name).header("CustomHeader", headerValue).build();
+ }
+
+ @Path("/bookstoresub")
+ public BookStore echoThroughBookStoreSub() {
+ return this;
+ }
+
+ @POST
+ @Path("/booksecho2")
+ @Consumes("text/plain")
+ @Produces("text/plain")
+ public Response echoBookNameAndHeader2(String name) {
+ return echoBookNameAndHeader(httpHeaders.getRequestHeader("CustomHeader").get(0), name);
+ }
+
@GET
@Path("/cd/{CDId}/")
public CD getCD() {