[prev in list] [next in list] [prev in thread] [next in thread]
List: wink-commits
Subject: svn commit: r891982 - in /incubator/wink/trunk:
From: rott () apache ! org
Date: 2009-12-17 23:20:44
Message-ID: 20091217232045.3189523889E7 () eris ! apache ! org
[Download RAW message or body]
Author: rott
Date: Thu Dec 17 23:20:44 2009
New Revision: 891982
URL: http://svn.apache.org/viewvc?rev=891982&view=rev
Log:
support usage of custom providers during AtomEntry->AtomContent->value retrieval when \
outside the scope of the thread local store of the client-server thread.
Added:
incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/ClientAtomTest.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntryProvider.java
Modified:
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/model/ModelUtils.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntrySyndEntryProvider.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/atom/AtomContent.java
incubator/wink/trunk/wink-common/src/main/resources/META-INF/core/wink-providers
Added: incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/ClientAtomTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/ClientAtomTest.java?rev=891982&view=auto
==============================================================================
--- incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/ClientAtomTest.java \
(added)
+++ incubator/wink/trunk/wink-client/src/test/java/org/apache/wink/client/ClientAtomTest.java \
Thu Dec 17 23:20:44 2009 @@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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.wink.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.wink.common.internal.providers.entity.xml.JAXBXmlProvider;
+import org.apache.wink.common.model.atom.AtomEntry;
+
+public class ClientAtomTest extends BaseTest {
+
+// @Path("atomresource")
+// private class MyAtomResource {
+// @Path("entry")
+// @GET
+// @Produces("application/atom+xml")
+// public Response getEntry() {
+// MyPojo myPojo = new MyPojo();
+// myPojo.setTitle("wheeee!!!");
+// // wrap POJO (JAXB object) in AtomContent, AtomEntry
+// return Response.status(Status.OK).entity(wrapInAtom(myPojo)).build();
+// }
+//
+// /*
+// * utility method to wrap responses in AtomEntry
+// */
+// private AtomEntry wrapInAtom(Object obj) {
+// AtomContent atomContent = new AtomContent();
+// atomContent.setType(MediaType.APPLICATION_XML);
+// atomContent.setValue(obj);
+// AtomEntry retAtomEntry = new AtomEntry();
+// retAtomEntry.setContent(atomContent);
+// return retAtomEntry;
+// }
+// }
+
+ @XmlRootElement(name = "mypojo", namespace = "http://mypojons/")
+ @XmlType(name = "mypojo", propOrder = {"title"})
+ protected static class MyPojo {
+
+ private String title;
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ }
+
+ private RestClient getRestClient() {
+ return new RestClient(new ClientConfig().applications(new Application() {
+
+ @Override
+ public Set<Object> getSingletons() {
+ return null;
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> set = new HashSet<Class<?>>();
+ set.add(MyProvider.class);
+ return set;
+ }
+
+ }));
+ }
+
+ @Provider
+ @Consumes( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+ @Produces( {MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.WILDCARD})
+ public static class MyProvider extends JAXBXmlProvider {
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public Object readFrom(Class<Object> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders,
+ InputStream entityStream) throws IOException,
+ WebApplicationException {
+ MyPojo myPojo = (MyPojo)super.readFrom(type, genericType, annotations, \
mediaType, httpHeaders, + entityStream);
+ String oldTitle = myPojo.getTitle();
+ myPojo.setTitle(oldTitle + " -- MyProvider was here.");
+ return myPojo;
+ }
+
+ }
+
+ private final static String responseString = "<?xml version=\"1.0\" \
encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<entry \
xmlns=\"http://www.w3.org/2005/Atom\" \
xmlns:ns2=\"http://a9.com/-/spec/opensearch/1.1/\" \
xmlns:ns3=\"http://www.w3.org/1999/xhtml\">" + + "<content \
type=\"application/xml\">" + + "<ns2:mypojo xmlns:ns2=\"http://mypojons/\">" +
+ "<title xmlns:ns5=\"http://www.w3.org/2005/Atom\" xmlns=\"\">wheeee!!!</title>" \
+ + "</ns2:mypojo>" +
+ "</content>" +
+ "</entry>";
+
+ public void testAtomContentRetrieval() {
+ server.setMockResponseCode(200);
+ server.setMockResponseContentType(MediaType.APPLICATION_ATOM_XML);
+ server.setMockResponseContent(responseString);
+ RestClient client = getRestClient();
+ Resource resource = client.resource(serviceURL + "/atomresource/entry");
+
+ // do get with response
+ ClientResponse clientResponse = resource.get();
+ // unwrap the AtomEntry, AtomContent value
+ MyPojo myPojo = \
(MyPojo)clientResponse.getEntity(AtomEntry.class).getContent().getValue(MyPojo.class);
+
+ // Confirm that the custom MyProvider is used during \
AtomContent.getValue(MyPojo.class) call. + // Custom providers are stored on \
the client-server transaction's thread local store. This assertion + // \
ensures that the custom providers are held long enough for a client application to \
use them during + // retrieval of the value from the AtomContent object, which \
occurs in its own thread. +
+ assertEquals("wheeee!!! -- MyProvider was here.", myPojo.getTitle());
+
+ }
+
+}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/model/ModelUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/a \
pache/wink/common/internal/model/ModelUtils.java?rev=891982&r1=891981&r2=891982&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/model/ModelUtils.java \
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/model/ModelUtils.java \
Thu Dec 17 23:20:44 2009 @@ -22,6 +22,7 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.annotation.Annotation;
@@ -39,6 +40,7 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Providers;
+import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -60,6 +62,7 @@
import org.apache.wink.common.internal.lifecycle.ScopeLifecycleManager;
import org.apache.wink.common.internal.registry.ProvidersRegistry;
import org.apache.wink.common.internal.registry.metadata.ProviderMetadataCollector;
+import org.apache.wink.common.internal.runtime.AbstractRuntimeContext;
import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.common.internal.utils.UnmodifiableMultivaluedMap;
import org.apache.wink.common.model.atom.AtomContent;
@@ -215,6 +218,7 @@
Annotation[] annotations,
MultivaluedMap<String, String> httpHeaders,
MediaType mediaType) throws IOException {
+
if (list == null || list.isEmpty()) {
return null;
}
@@ -293,10 +297,37 @@
providers = new ProvidersImpl(providersRegistry, \
runtimeContext); }
}
+
+ /*
+ * Need to set a temporary RuntimeContextTLS just in case we're already \
outside of the runtime context. + * This may occur when a client app is \
retrieving the AtomContent value, expecting it to be unmarshalled + * \
automatically, but we are already outside of the client-server thread, and thus no \
longer have a + * RuntimeContextTLS from which to retrieve or inject \
providers. + */
+
+ RuntimeContext tempRuntimeContext = \
RuntimeContextTLS.getRuntimeContext(); + if (tempRuntimeContext == null) {
+ final Providers p = providers;
+ RuntimeContextTLS.setRuntimeContext(new AbstractRuntimeContext() {
+ {
+ setAttribute(Providers.class, p);
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return null;
+ }
+ });
+ }
+
MessageBodyReader<T> reader =
providers.getMessageBodyReader(type, type, EMPTY_ARRAY, mediaType);
if (reader == null)
throw new \
WebApplicationException(Response.Status.UNSUPPORTED_MEDIA_TYPE); +
T read =
reader.readFrom(type,
type,
@@ -304,6 +335,10 @@
mediaType,
httpHeaders,
new ByteArrayInputStream((byte[])value));
+
+ // Reset RuntimeContext from temporary above. tempRuntimeContext may be \
null here, which is ok. + \
RuntimeContextTLS.setRuntimeContext(tempRuntimeContext); +
return read;
}
throw new ClassCastException("Cannot cast " + value.getClass().getName()
Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntryProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/a \
pache/wink/common/internal/providers/entity/atom/AtomEntryProvider.java?rev=891982&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntryProvider.java \
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntryProvider.java \
Thu Dec 17 23:20:44 2009 @@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.wink.common.internal.providers.entity.atom;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.ext.Providers;
+
+import org.apache.wink.common.internal.providers.entity.xml.JAXBXmlProvider;
+import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
+import org.apache.wink.common.internal.utils.MediaTypeUtils;
+import org.apache.wink.common.model.atom.AtomContent;
+import org.apache.wink.common.model.atom.AtomEntry;
+
+@Provider
+@Consumes( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, \
MediaTypeUtils.JAVASCRIPT}) +@Produces( {MediaType.APPLICATION_ATOM_XML, \
MediaType.APPLICATION_JSON, MediaTypeUtils.JAVASCRIPT}) +public class \
AtomEntryProvider extends JAXBXmlProvider { +
+ @Override
+ public boolean isReadable(Class<?> type,
+ Type genericType,
+ Annotation[] annotations,
+ MediaType mediaType) {
+ return type == AtomEntry.class;
+ }
+
+ @Override
+ public Object readFrom(Class<Object> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+
+
+ AtomEntry atomEntry = (AtomEntry) super.readFrom(type, genericType, \
annotations, mediaType, httpHeaders, + entityStream);
+
+ /*
+ * The value in the AtomContent object is arbitrary, set by the server. We \
want to use the + * built-in AND client application supplied providers. \
Because these providers are collected + * on the thread local store, and the \
unmarshalling of the AtomContent value is done lazily + * (after the \
client-server context has expired), we need some way to hold onto the Providers + \
* long enough for the client app to be able to seamlessly get the value off the \
AtomContent + * object. Thus the need to set the *real* providers list on \
the AtomContent object, so it + * can use the list to pass to ModelUtils when \
it needs to retrieve and unmarshal the AtomContent + * value.
+ *
+ * We have to be careful to use the real Providers list instead of the one \
from the injected + * local providers field in this class. The injected \
object may be a "proxy" to the real + * providers, and could cause an \
infinite loop when ModelUtils.readValue calls back through + * the providers.
+ */
+ AtomContent content = atomEntry.getContent();
+ if (content != null) {
+ content.setProviders(RuntimeContextTLS.getRuntimeContext().getAttribute(Providers.class));
+ }
+
+ return atomEntry;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return false; // so JAXBXmlProvider will do the write
+ }
+
+}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntrySyndEntryProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/a \
pache/wink/common/internal/providers/entity/atom/AtomEntrySyndEntryProvider.java?rev=891982&r1=891981&r2=891982&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntrySyndEntryProvider.java \
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/atom/AtomEntrySyndEntryProvider.java \
Thu Dec 17 23:20:44 2009 @@ -37,7 +37,9 @@
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
+import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
import org.apache.wink.common.internal.utils.MediaTypeUtils;
+import org.apache.wink.common.model.atom.AtomContent;
import org.apache.wink.common.model.atom.AtomEntry;
import org.apache.wink.common.model.synd.SyndEntry;
@@ -72,6 +74,27 @@
mediaType,
httpHeaders,
entityStream);
+
+ /*
+ * The value in the AtomContent object is arbitrary, set by the server. We \
want to use the + * built-in AND client application supplied providers. \
Because these providers are collected + * on the thread local store, and the \
unmarshalling of the AtomContent value is done lazily + * (after the \
client-server context has expired), we need some way to hold onto the Providers + \
* long enough for the client app to be able to seamlessly get the value off the \
AtomContent + * object. Thus the need to set the *real* providers list on \
the AtomContent object, so it + * can use the list to pass to ModelUtils when \
it needs to retrieve and unmarshal the AtomContent + * value.
+ *
+ * We have to be careful to use the real Providers list instead of the one \
from the injected + * local providers field in this class. The injected \
object may be a "proxy" to the real + * providers, and could cause an \
infinite loop when ModelUtils.readValue calls back through + * the providers.
+ */
+ AtomContent content = entry.getContent();
+ if (content != null) {
+ content.setProviders(RuntimeContextTLS.getRuntimeContext().getAttribute(Providers.class));
+ }
+
return entry.toSynd(new SyndEntry());
}
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/a \
pache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java?rev=891982&r1=891981&r2=891982&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java \
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/providers/entity/xml/AbstractJAXBProvider.java \
Thu Dec 17 23:20:44 2009 @@ -63,7 +63,7 @@
\
new SoftConcurrentMap<Class<?>, JAXBContext>();
@Context
- private Providers providers;
+ protected Providers providers;
private static final SoftConcurrentMap<Class<?>, Boolean> \
jaxbIsXMLRootElementCache =
\
new SoftConcurrentMap<Class<?>, Boolean>();
Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/atom/AtomContent.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/a \
pache/wink/common/model/atom/AtomContent.java?rev=891982&r1=891981&r2=891982&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/atom/AtomContent.java \
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/model/atom/AtomContent.java \
Thu Dec 17 23:20:44 2009 @@ -199,6 +199,9 @@
@XmlTransient
private Object savedValue = null;
+ @XmlTransient
+ private Providers providers;
+
public AtomContent() {
}
@@ -224,6 +227,18 @@
value.setValue(getValue(Object.class));
return value;
}
+
+ /**
+ * Sets the Providers on a local field so that the registry of custom and system
+ * providers is available when a client application retrieves the value, \
expecting + * it to be seamlessly unmarshalled or converted to the expected type \
declared in + * getValue(Class).
+ *
+ * Client applications should NOT call this method.
+ */
+ public void setProviders(Providers _providers) {
+ providers = _providers;
+ }
/**
* Gets the value of type.
@@ -339,7 +354,7 @@
try {
return getValue(cls,
cls,
- null,
+ providers,
ModelUtils.EMPTY_ARRAY,
ModelUtils.EMPTY_STRING_MAP,
ModelUtils.determineMediaType(type));
Modified: incubator/wink/trunk/wink-common/src/main/resources/META-INF/core/wink-providers
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/resources/META-INF/core/wink-providers?rev=891982&r1=891981&r2=891982&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/resources/META-INF/core/wink-providers \
(original)
+++ incubator/wink/trunk/wink-common/src/main/resources/META-INF/core/wink-providers \
Thu Dec 17 23:20:44 2009 @@ -38,12 +38,12 @@
org.apache.wink.common.internal.providers.entity.SourceProvider$DOMSourceProvider
org.apache.wink.common.internal.providers.entity.StreamingOutputProvider
-
# JAXB Providers
org.apache.wink.common.internal.providers.entity.xml.JAXBElementXmlProvider
org.apache.wink.common.internal.providers.entity.xml.JAXBXmlProvider
# Atom
+org.apache.wink.common.internal.providers.entity.atom.AtomEntryProvider
org.apache.wink.common.internal.providers.entity.atom.AtomFeedSyndFeedProvider
org.apache.wink.common.internal.providers.entity.atom.AtomEntrySyndEntryProvider
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic