Author: sergeyb
Date: Wed Apr 6 10:37:41 2011
New Revision: 1089390
URL: http://svn.apache.org/viewvc?rev=1089390&view=rev
Log:
[CXF-3415] Making sure contexts are injected into cloned JAXB providers
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=1089390&r1=1089389&r2=1089390&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
Wed Apr 6 10:37:41 2011
@@ -97,8 +97,6 @@ public final class ProviderFactory {
private RequestPreprocessor requestPreprocessor;
private ProviderInfo<Application> application;
- private Set<Object> clonedProviders = new HashSet<Object>();
-
private ProviderFactory() {
}
@@ -289,33 +287,46 @@ public final class ProviderFactory {
m);
//If none found try the default ones
- if (mr != null || this == SHARED_FACTORY) {
+ if (mr != null) {
return mr;
}
- mr = SHARED_FACTORY.createMessageBodyReader(bodyType, parameterType,
- parameterAnnotations,
mediaType, m);
- return (MessageBodyReader)cloneSharedProviderIfNeeded(mr);
- }
-
- private Object cloneSharedProviderIfNeeded(Object sharedProvider) {
- if (sharedProvider != null) {
- String clsName = sharedProvider.getClass().getName();
- if (JAXB_PROVIDER_NAME.equals(clsName) ||
JSON_PROVIDER_NAME.equals(clsName)) {
- try {
- synchronized (this) {
- for (Object cloned : clonedProviders) {
- if (cloned.getClass().getName().equals(clsName)) {
- return cloned;
- }
+ mr = SHARED_FACTORY.chooseMessageReader(bodyType,
+ parameterType,
+ parameterAnnotations,
+ mediaType,
+ m);
+ return (MessageBodyReader)cloneSharedProviderIfNeeded(mr, m);
+ }
+
+ private boolean isJaxbBasedProvider(Object sharedProvider) {
+ String clsName = sharedProvider.getClass().getName();
+ return JAXB_PROVIDER_NAME.equals(clsName) ||
JSON_PROVIDER_NAME.equals(clsName);
+ }
+
+ private Object cloneSharedProviderIfNeeded(Object sharedProvider, Message
m) {
+ if (sharedProvider != null && isJaxbBasedProvider(sharedProvider)) {
+ try {
+ synchronized (this) {
+ ProviderInfo<?> info = null;
+ for (int i = messageReaders.size() - 1; i >= 0; i--) {
+ ProviderInfo<?> lastInfo = messageReaders.get(i);
+ if (lastInfo.getProvider().getClass().getName().equals(
+ sharedProvider.getClass().getName())) {
+ info = lastInfo;
+ break;
}
- Object provider =
sharedProvider.getClass().newInstance();
- clonedProviders.add(provider);
- setProviders(false, provider);
- return provider;
}
- } catch (Exception ex) {
- // won't happen at this stage
+ if (info == null) {
+ setProviders(false,
sharedProvider.getClass().newInstance());
+ info = messageReaders.get(messageReaders.size() - 1);
+ }
+ InjectionUtils.injectContextFields(info.getProvider(),
info, m);
+ InjectionUtils.injectContextMethods(info.getProvider(),
info, m);
+
+ return info.getProvider();
}
+ } catch (Exception ex) {
+ // won't happen at this stage
}
}
return sharedProvider;
@@ -363,12 +374,15 @@ public final class ProviderFactory {
m);
//If none found try the default ones
- if (mw != null || this == SHARED_FACTORY) {
+ if (mw != null) {
return mw;
}
- mw = SHARED_FACTORY.createMessageBodyWriter(bodyType, parameterType,
- parameterAnnotations,
mediaType, m);
- return (MessageBodyWriter)cloneSharedProviderIfNeeded(mw);
+ mw = SHARED_FACTORY.chooseMessageWriter(bodyType,
+ parameterType,
+ parameterAnnotations,
+ mediaType,
+ m);
+ return (MessageBodyWriter)cloneSharedProviderIfNeeded(mw, m);
}
//CHECKSTYLE:OFF
@@ -426,6 +440,9 @@ public final class ProviderFactory {
for (List<?> list : providerLists) {
for (Object p : list) {
ProviderInfo pi = (ProviderInfo)p;
+ //if (ProviderFactory.SHARED_FACTORY == this &&
isJaxbBasedProvider(pi.getProvider())) {
+ // continue;
+ //}
InjectionUtils.injectContextProxies(pi, pi.getProvider());
}
}
@@ -468,8 +485,10 @@ public final class ProviderFactory {
for (ProviderInfo<MessageBodyReader> ep : messageReaders) {
if (matchesReaderCriterias(ep.getProvider(), type, genericType,
annotations, mediaType)) {
if (this == SHARED_FACTORY) {
- InjectionUtils.injectContextFields(ep.getProvider(), ep,
m);
- InjectionUtils.injectContextMethods(ep.getProvider(), ep,
m);
+ if (!isJaxbBasedProvider(ep.getProvider())) {
+ InjectionUtils.injectContextFields(ep.getProvider(),
ep, m);
+ InjectionUtils.injectContextMethods(ep.getProvider(),
ep, m);
+ }
return ep.getProvider();
}
handleMapper((List)candidates, ep, type, m,
MessageBodyReader.class);
@@ -522,8 +541,10 @@ public final class ProviderFactory {
for (ProviderInfo<MessageBodyWriter> ep : messageWriters) {
if (matchesWriterCriterias(ep.getProvider(), type, genericType,
annotations, mediaType)) {
if (this == SHARED_FACTORY) {
- InjectionUtils.injectContextFields(ep.getProvider(), ep,
m);
- InjectionUtils.injectContextMethods(ep.getProvider(), ep,
m);
+ if (!isJaxbBasedProvider(ep.getProvider())) {
+ InjectionUtils.injectContextFields(ep.getProvider(),
ep, m);
+ InjectionUtils.injectContextMethods(ep.getProvider(),
ep, m);
+ }
return ep.getProvider();
}
handleMapper((List)candidates, ep, type, m,
MessageBodyWriter.class);
@@ -700,9 +721,7 @@ public final class ProviderFactory {
}
public void initProviders(List<ClassResourceInfo> cris) {
- Set<Object> set = new HashSet<Object>();
- set.addAll(messageReaders);
- set.addAll(messageWriters);
+ Set<Object> set = getReadersWriters();
for (Object o : set) {
Object provider = ((ProviderInfo)o).getProvider();
if (provider instanceof AbstractConfigurableProvider) {
@@ -714,6 +733,13 @@ public final class ProviderFactory {
}
}
+ Set<Object> getReadersWriters() {
+ Set<Object> set = new HashSet<Object>();
+ set.addAll(messageReaders);
+ set.addAll(messageWriters);
+ return set;
+ }
+
private static class ExceptionMapperComparator implements
Comparator<ExceptionMapper<? extends Throwable>> {
Modified:
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java?rev=1089390&r1=1089389&r2=1089390&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/ProviderFactoryTest.java
Wed Apr 6 10:37:41 2011
@@ -29,6 +29,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
@@ -36,6 +40,7 @@ import javax.ws.rs.WebApplicationExcepti
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.MessageBodyReader;
@@ -51,6 +56,7 @@ import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.jaxrs.Customer;
import org.apache.cxf.jaxrs.CustomerParameterHandler;
import org.apache.cxf.jaxrs.JAXBContextProvider;
+import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.ext.ParameterHandler;
import org.apache.cxf.jaxrs.ext.RequestHandler;
import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper;
@@ -67,6 +73,7 @@ import org.easymock.classextension.EasyM
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
public class ProviderFactoryTest extends Assert {
@@ -130,24 +137,73 @@ public class ProviderFactoryTest extends
@Test
public void testDefaultJaxbProviderCloned() {
ProviderFactory pf = ProviderFactory.getInstance();
+ doTestDefaultJaxbProviderCloned(pf, "http://localhost:8080/base/");
+ checkJaxbProvider(pf);
+ }
+
+ @Test
+ public void testDefaultJaxbProviderClonedMultipleThreads() throws
Exception {
+ ProviderFactory pf = ProviderFactory.getInstance();
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 0,
TimeUnit.SECONDS,
+ new
ArrayBlockingQueue<Runnable>(10));
+ CountDownLatch startSignal = new CountDownLatch(1);
+ CountDownLatch doneSignal = new CountDownLatch(5);
+
+ executor.execute(new TestRunnable(pf, startSignal, doneSignal,
"http://localhost:8080/base/1"));
+ executor.execute(new TestRunnable(pf, startSignal, doneSignal,
"http://localhost:8080/base/2"));
+ executor.execute(new TestRunnable(pf, startSignal, doneSignal,
"http://localhost:8080/base/3"));
+ executor.execute(new TestRunnable(pf, startSignal, doneSignal,
"http://localhost:8080/base/4"));
+ executor.execute(new TestRunnable(pf, startSignal, doneSignal,
"http://localhost:8080/base/5"));
+
+ startSignal.countDown();
+ doneSignal.await(10, TimeUnit.SECONDS);
+ executor.shutdownNow();
+ assertEquals("Not all invocations have completed", 0,
doneSignal.getCount());
+ checkJaxbProvider(pf);
+ }
+
+ private void doTestDefaultJaxbProviderCloned(ProviderFactory pf, String
property) {
+ Message message = new MessageImpl();
+ message.put(Message.QUERY_STRING, "uri=" + property);
MessageBodyReader customJaxbReader =
pf.createMessageBodyReader((Class<?>)Book.class, null, null,
-
MediaType.TEXT_XML_TYPE, new MessageImpl());
+
MediaType.TEXT_XML_TYPE, message);
assertTrue(customJaxbReader instanceof JAXBElementProvider);
+ JAXBElementProvider provider = (JAXBElementProvider)customJaxbReader;
+ MessageContext mc = provider.getContext();
+ assertNotNull(mc);
+ UriInfo ui = mc.getUriInfo();
+ MultivaluedMap<String, String> queries = ui.getQueryParameters();
+ assertEquals(1, queries.size());
+ List<String> uriQuery = queries.get("uri");
+ assertEquals(1, uriQuery.size());
+ assertEquals(property, uriQuery.get(0));
+
+
MessageBodyReader customJaxbReader2 =
pf.createMessageBodyReader((Class<?>)Book.class, null, null,
-
MediaType.TEXT_XML_TYPE, new MessageImpl());
+
MediaType.TEXT_XML_TYPE, message);
assertSame(customJaxbReader, customJaxbReader2);
-
+
MessageBodyWriter customJaxbWriter =
pf.createMessageBodyWriter((Class<?>)Book.class, null, null,
-
MediaType.TEXT_XML_TYPE, new MessageImpl());
+
MediaType.TEXT_XML_TYPE, message);
assertSame(customJaxbReader, customJaxbWriter);
MessageBodyReader jaxbReader =
ProviderFactory.getSharedInstance().createMessageBodyReader(
- (Class<?>)Book.class, null, null, MediaType.TEXT_XML_TYPE, new
MessageImpl());
+ (Class<?>)Book.class, null, null, MediaType.TEXT_XML_TYPE,
message);
assertTrue(jaxbReader instanceof JAXBElementProvider);
assertNotSame(jaxbReader, customJaxbReader);
}
+ private void checkJaxbProvider(ProviderFactory pf) {
+ int count = 0;
+ for (Object provider : pf.getReadersWriters()) {
+ if (((ProviderInfo)provider).getProvider() instanceof
JAXBElementProvider) {
+ count++;
+ }
+ }
+ assertEquals(1, count);
+ }
+
@Test
public void testCustomJaxbProvider() {
ProviderFactory pf = ProviderFactory.getInstance();
@@ -731,4 +787,35 @@ public class ProviderFactoryTest extends
}
}
+
+ @Ignore
+ private class TestRunnable implements Runnable {
+
+ private CountDownLatch startSignal;
+ private CountDownLatch doneSignal;
+ private ProviderFactory pf;
+ private String property;
+ public TestRunnable(ProviderFactory pf,
+ CountDownLatch startSignal,
+ CountDownLatch doneSignal,
+ String property) {
+ this.startSignal = startSignal;
+ this.doneSignal = doneSignal;
+ this.pf = pf;
+ this.property = property;
+ }
+
+ public void run() {
+
+ try {
+ startSignal.await();
+ ProviderFactoryTest.this.doTestDefaultJaxbProviderCloned(pf,
property);
+ doneSignal.countDown();
+ } catch (Exception ex) {
+ Assert.fail(ex.getMessage());
+ }
+
+ }
+
+ }
}