cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r887317 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ rt/frontend/jaxrs/src/main/java/...
Date Fri, 04 Dec 2009 18:46:08 GMT
Author: sergeyb
Date: Fri Dec  4 18:46:07 2009
New Revision: 887317

URL: http://svn.apache.org/viewvc?rev=887317&view=rev
Log:
Adding AtomPojoProvider plus few minor fixes

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java   (with props)
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.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/provider/RequestDispatcherProvider.java
    cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java Fri Dec  4 18:46:07 2009
@@ -371,7 +371,7 @@
 
         InputStream inputStream = (InputStream)r.getEntity();
         if (inputStream == null) {
-            return cls == Response.class ? cls : null;
+            return cls == Response.class ? r : null;
         }
         try {
             int status = conn.getResponseCode();
@@ -379,7 +379,7 @@
                 Object length = r.getMetadata().getFirst(HttpHeaders.CONTENT_LENGTH);
                 if (length == null || Integer.parseInt(length.toString()) == 0
                     || status >= 400) {
-                    return cls == Response.class ? cls : null;
+                    return cls == Response.class ? r : cls == InputStream.class ? inputStream : null;
                 }
             }
         } catch (IOException ex) {
@@ -550,7 +550,6 @@
         
         m.put(Message.CONTENT_TYPE, headers.getFirst(HttpHeaders.CONTENT_TYPE));
         
-        
         Exchange exchange = new ExchangeImpl();
         exchange.setSynchronous(true);
         exchange.setOutMessage(m);

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/client/WebClient.java Fri Dec  4 18:46:07 2009
@@ -302,7 +302,7 @@
      * @param memberClass expected type of collection member class
      * @return typed collection
      */
-    public <T> Collection<T> invokeAndGetCollection(String httpMethod, Object body, 
+    public <T> Collection<? extends T> invokeAndGetCollection(String httpMethod, Object body, 
                                                     Class<T> memberClass) {
         
         Response r = doInvoke(httpMethod, body, Collection.class, memberClass);

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,120 @@
+/**
+ * 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.jaxrs.ext.atom;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.jaxrs.ext.MessageContext;
+
+/**
+ * A callback-style provider which can be used to map an object to Atom Feed or Entry
+ * without having to deal directly with types representing Atom feeds or entries
+ * 
+ * @param <T> Type of objects which will be mapped to feeds or entries
+ */
+public abstract class AbstractAtomElementBuilder<T> {
+    
+    private MessageContext mc;
+    
+    /**
+     * Sets MessageContext
+     * @param context message context
+     */
+    public void setMessageContext(MessageContext context) {
+        mc = context;
+    }
+    
+    /**
+     * returns MessageContext
+     * @return message context
+     */
+    public MessageContext getMessageContext() {
+        return mc;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element title
+     */
+    public String getTitle(T pojo) {
+        return null;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element author
+     */
+    public String getAuthor(T pojo) {
+        return null;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element id
+     */
+    public String getId(T pojo) {
+        return null;
+    }
+
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return base uri
+     */
+    public String getBaseUri(T pojo) {
+        return null;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element updated date
+     */
+    public String getUpdated(T pojo) {
+        return null;
+    }
+    
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element categories
+     */
+    public List<String> getCategories(T pojo) {
+        return null;
+    }
+    
+    
+    //CHECKSTYLE:OFF
+    /**
+     * Returns a map of link URI to link relations type pairs 
+     * See {@link <a href="http://www.iana.org/assignments/link-relations/link-relations.xml">Atom Link Relations</a>}.
+     *
+     * @param pojo Object which is being mapped
+     * @return the map of link URI to link relations type pairs 
+     */
+    //CHECKSTYLE:ON
+    public Map<String, String> getLinks(T pojo) {
+        return null;
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractAtomElementBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,45 @@
+/**
+ * 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.jaxrs.ext.atom;
+
+/**
+ * A callback-style provider which can be used to map an object to Atom Entry
+ * without having to deal directly with types representing Atom entries
+ * 
+ * @param <T> Type of objects which will be mapped to entries
+ */
+public abstract class AbstractEntryBuilder<T> extends AbstractAtomElementBuilder<T> {
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element publication date
+     */
+    public String getPublished(T pojo) {
+        return null;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return element summary
+     */
+    public String getSummary(T pojo) {
+        return null;
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractEntryBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,48 @@
+/**
+ * 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.jaxrs.ext.atom;
+
+/**
+ * A callback-style provider which can be used to map an object to Atom Feed
+ * without having to deal directly with types representing Atom feeds
+ * 
+ * @param <T> Type of objects which will be mapped to feeds or entries
+ */
+public abstract class AbstractFeedBuilder<T> extends AbstractAtomElementBuilder<T> {
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return feed icon uri
+     */
+    public String getIcon(T pojo) {
+        return null;
+    }
+    
+    /**
+     * 
+     * @param pojo Object which is being mapped
+     * @return feed logo uri
+     */
+    public String getLogo(T pojo) {
+        return null;
+    }
+    
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AbstractFeedBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,39 @@
+/**
+ * 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.jaxrs.ext.atom;
+
+import org.apache.abdera.model.Element;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+
+/**
+ * A callback-style interface which can be used to deserialize an Atom Feed or Entry into a custom object
+ * without having to introduce direct dependencies on Abdera API in the 'main' service code  
+ * 
+ * @param <T> Type of Atom element, Feed or Entry
+ * @param <E> Type of objects which will be deseriaized from feed or entry
+ *  
+ */
+public interface AtomElementReader<T extends Element, E> {
+    /**
+     * @param element Feed or Entry instance 
+     * @param context current MessageContext
+     * @return pojoElement 
+     */
+    E readFrom(T element, MessageContext mc);
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementReader.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,40 @@
+/**
+ * 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.jaxrs.ext.atom;
+
+import org.apache.abdera.model.Element;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+
+/**
+ * A callback-style interface which can be used to map an object to an Atom Feed or Entry
+ * without having to introduce direct dependencies on Abdera API in the 'main' service code  
+ * 
+ * @param <T> Type of Atom element, Feed or Entry
+ * @param <E> Type of objects which will be mapped to feed or entry
+ *  
+ */
+public interface AtomElementWriter<T extends Element, E> {
+    /**
+     * @param element Feed or Entry instance 
+     * @param pojoElement An object which needs to be mapped to the feed or entry
+     * @param context modifiable output headers
+     * @param context MessageContext which can be used for adding properties related to the current URI, etc
+     */
+    void writeTo(T element, E pojoElement, MessageContext mc);
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/atom/AtomElementWriter.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/HttpServletResponseFilter.java Fri Dec  4 18:46:07 2009
@@ -19,6 +19,9 @@
 package org.apache.cxf.jaxrs.impl;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
@@ -45,4 +48,29 @@
         return new ServletOutputStreamFilter(super.getOutputStream(), m);
     }
     
+    @Override
+    public void setHeader(String name, String value) {
+        setHeaderInternal(name, value, false);
+    }
+    
+    @Override
+    public void addHeader(String name, String value) {
+        setHeaderInternal(name, value, true);
+    }
+    
+    @SuppressWarnings("unchecked")
+    private void setHeaderInternal(String name, String value, boolean add) {
+        Map<String, List<String>> headers = 
+            (Map<String, List<String>>)m.get(Message.PROTOCOL_HEADERS);
+        List<String> values = headers.get(name);
+        if (values == null) {
+            values = new ArrayList<String>();
+            headers.put(name, values);
+        }
+        if (!add) {
+            values.clear();
+        }
+        values.add(value);
+    }
 }
+

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=887317&r1=887316&r2=887317&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 Fri Dec  4 18:46:07 2009
@@ -232,10 +232,19 @@
             LOG.fine("Response content type is: " + responseType.toString());
             message.put(Message.CONTENT_TYPE, responseType.toString());
             
+            Annotation[] annotations = invoked != null ? invoked.getAnnotations() : new Annotation[]{};
+            
+            long size = writer.getSize(entity, targetType, genericType, annotations, responseType);
+            if (size > 0) {
+                LOG.fine("Setting ContentLength to " + size + " as requested by " 
+                         + writer.getClass().getName());
+                responseHeaders.putSingle(HttpHeaders.CONTENT_LENGTH, Long.toString(size));
+            }
+            
             LOG.fine("Response EntityProvider is: " + writer.getClass().getName());
             try {
                 writer.writeTo(entity, targetType, genericType, 
-                               invoked != null ? invoked.getAnnotations() : new Annotation[]{}, 
+                               annotations, 
                                responseType, 
                                responseHeaders, 
                                message.getContent(OutputStream.class));

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,509 @@
+/**
+ * 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.jaxrs.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.ExtensibleElement;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.writer.Writer;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.atom.AbstractAtomElementBuilder;
+import org.apache.cxf.jaxrs.ext.atom.AbstractEntryBuilder;
+import org.apache.cxf.jaxrs.ext.atom.AbstractFeedBuilder;
+import org.apache.cxf.jaxrs.ext.atom.AtomElementReader;
+import org.apache.cxf.jaxrs.ext.atom.AtomElementWriter;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
+
+@Produces({"application/atom+xml", "application/atom+xml;type=feed", "application/atom+xml;type=entry" })
+@Consumes({"application/atom+xml", "application/atom+xml;type=feed", "application/atom+xml;type=entry" })
+@Provider
+public class AtomPojoProvider extends AbstractConfigurableProvider
+    implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(AtomPojoProvider.class);
+    private static final Abdera ATOM_ENGINE = new Abdera();
+    
+    private JAXBElementProvider jaxbProvider = new JAXBElementProvider();
+    private Map<String, String> collectionGetters = Collections.emptyMap();
+    private Map<String, String> collectionSetters = Collections.emptyMap();
+    private Map<String, AtomElementWriter<?, ?>> atomWriters = Collections.emptyMap();
+    private Map<String, AtomElementReader<?, ?>> atomReaders = Collections.emptyMap();
+    private Map<String, AbstractAtomElementBuilder<?>> atomBuilders = Collections.emptyMap();
+    
+    private MessageContext mc;   
+    private boolean formattedOutput;
+    
+    @Context
+    public void setMessageContext(MessageContext context) {
+        mc = context;
+        for (AbstractAtomElementBuilder builder : atomBuilders.values()) {
+            builder.setMessageContext(context);
+        }
+    }
+    
+    public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mt) {
+        return -1;
+    }
+    
+    public void setCollectionGetters(Map<String, String> methods) {
+        collectionGetters = methods;
+    }
+    
+    public void setCollectionSetters(Map<String, String> methods) {
+        collectionSetters = methods;
+    }
+
+    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mt) {
+        return !Feed.class.isAssignableFrom(type) && !Entry.class.isAssignableFrom(type);
+    }
+
+    public void writeTo(Object o, Class<?> clazz, Type genericType, Annotation[] annotations, 
+                        MediaType mt, MultivaluedMap<String, Object> headers, OutputStream os)
+        throws IOException {
+        boolean isFeed = isFeedRequested(mt);        
+        boolean isCollection = InjectionUtils.isSupportedCollectionOrArray(clazz);
+        
+        
+        if (isFeed && isCollection) {
+            reportError("Atom feed can only be created from a collection wrapper", null);
+        } else if (!isFeed && isCollection) {
+            reportError("Atom entry can only be created from a single object", null);
+        }
+        
+        Element atomElement = null;
+        try {
+            if (isFeed && !isCollection) {
+                atomElement = createFeedFromCollectionWrapper(o);
+            } else if (!isFeed && !isCollection) {
+                atomElement = createEntryFromObject(o, clazz);
+            }
+        } catch (Exception ex) {
+            throw new WebApplicationException(ex);
+        }
+        
+        try {
+            writeAtomElement(atomElement, os);
+        } catch (IOException ex) {
+            reportError("Atom element can not be serialized", ex);
+        }
+    }
+    
+    private void writeAtomElement(Element atomElement, OutputStream os) throws IOException {
+        if (formattedOutput) {
+            Writer w = ATOM_ENGINE.getWriterFactory().getWriter("prettyxml");
+            atomElement.writeTo(w, os);
+        } else {
+            atomElement.writeTo(os);
+        }
+    }
+    
+    public void setFormattedOutput(boolean formattedOutput) {
+        this.formattedOutput = formattedOutput;
+    }
+    
+    protected Feed createFeedFromCollectionWrapper(Object o) throws Exception {
+        
+        Factory factory = Abdera.getNewFactory();
+        Feed feed = factory.newFeed();
+        
+        boolean writerUsed = buildFeed(feed, o);
+        
+        if (feed.getEntries().size() > 0) {
+            return feed;
+        }
+        
+        String methodName = getCollectionMethod(o.getClass(), true);
+        Object collection = null;
+        Method m = null;
+        try {
+            m = o.getClass().getMethod(methodName, new Class[]{});
+            collection = m.invoke(o, new Object[]{});
+        } catch (Exception ex) {
+            reportError("Collection for " + o.getClass().getName() + " can not be retrieved", ex);
+        }
+        
+        setFeedFromCollection(factory, feed, o, collection, m.getReturnType(), m.getGenericReturnType(), 
+                              writerUsed);
+        return feed;
+    }
+    
+    private String getCollectionMethod(Class<?> cls, boolean getter) {
+        Map<String, String> map = getter ? collectionGetters : collectionSetters; 
+        String methodName = map.get(cls.getName());
+        if (methodName == null) {
+            try {
+                methodName = (getter ? "get" : "set") + cls.getSimpleName();
+                Class[] params = getter ? new Class[]{} : new Class[]{List.class};
+                cls.getMethod(methodName, params);
+            } catch (Exception ex) {
+                String type = getter ? "getter" : "setter";
+                reportError("Collection " + type + " method for " + cls.getName()
+                    + " has not been specified and no default " + methodName + " is available", null);
+            }
+        }
+        return methodName;
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected boolean buildFeed(Feed feed, Object o) {
+        AtomElementWriter<?, ?> builder = atomWriters.get(o.getClass().getName());
+        if (builder != null) {
+            ((AtomElementWriter)builder).writeTo(feed, o, mc);
+            return true;
+        }
+        return false;
+    }
+    
+    protected void setFeedFromCollection(Factory factory, Feed feed, Object wrapper, Object collection,
+        Class<?> collectionCls, Type collectionType, boolean writerUsed) throws Exception {
+        
+        Object[] arr = collectionCls.isArray() ? (Object[])collection : ((Collection)collection).toArray();
+        Class<?> memberClass = InjectionUtils.getActualType(collectionType);
+        
+        for (Object o : arr) {
+            Entry entry = createEntryFromObject(o, memberClass);
+            feed.addEntry(entry);
+        }
+        if (!writerUsed) {
+            setFeedProperties(factory, feed, wrapper, collection, collectionCls, collectionType);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected void setFeedProperties(Factory factory, Feed feed, Object wrapper, Object collection, 
+                                     Class<?> collectionCls, Type collectionType) {
+        
+        AbstractAtomElementBuilder<?> builder = atomBuilders.get(wrapper.getClass().getName());
+        if (builder == null) {
+            return;
+        }
+        setCommonElementProperties(factory, feed, builder, wrapper);
+        
+        AbstractFeedBuilder theBuilder = (AbstractFeedBuilder)builder;
+        
+        // the hierarchy is a bit broken in that we can not set author/title.etc on some
+        // common Feed/Entry super type
+        
+        String author = theBuilder.getAuthor(wrapper);
+        if (author != null) {
+            feed.addAuthor(author);
+        } else {
+            feed.addAuthor("CXF JAX-RS");
+        }
+        String title = theBuilder.getTitle(wrapper);
+        if (title != null) {
+            feed.setTitle(title);
+        } else {
+            feed.setTitle(String.format(wrapper.getClass().getSimpleName()
+                          + " collection with %d entry(ies)", feed.getEntries().size()));
+        }
+        
+        String id = theBuilder.getId(wrapper);
+        if (id != null) {
+            feed.setId(id);
+        } else {
+            feed.setId("uuid:" + UUID.randomUUID().toString());
+        }
+        String updated = theBuilder.getUpdated(wrapper);
+        if (updated != null) {
+            feed.setUpdated(updated);
+        } else {
+            feed.setUpdated(new Date());
+        }
+        
+        
+        Map<String, String> links = theBuilder.getLinks(wrapper);
+        if (links != null) {
+            for (Map.Entry<String, String> entry : links.entrySet()) {
+                feed.addLink(entry.getKey(), entry.getValue());
+            }
+        }
+        List<String> terms = theBuilder.getCategories(wrapper);
+        if (terms != null) {
+            for (String term : terms) {
+                feed.addCategory(term);
+            }
+        }
+        
+        
+        // feed specific
+        
+        String logo = theBuilder.getLogo(wrapper);
+        if (logo != null) {
+            feed.setLogo(logo);
+        }
+        String icon = theBuilder.getLogo(wrapper);
+        if (icon != null) {
+            feed.setIcon(icon);
+        }
+        
+    }
+    
+    
+    
+    protected Entry createEntryFromObject(Object o, Class<?> cls) throws Exception {
+        
+        Factory factory = Abdera.getNewFactory();
+        Entry entry = factory.getAbdera().newEntry();
+        
+        if (!buildEntry(entry, o)) {
+            setEntryProperties(factory, entry, o, cls);
+        }
+        
+        if (entry.getContentElement() == null 
+            && entry.getExtensions().size() == 0) {
+            createEntryContent(entry, o, cls);    
+        }
+        return entry;
+    
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected boolean buildEntry(Entry entry, Object o) {
+        AtomElementWriter<?, ?> builder = atomWriters.get(o.getClass().getName());
+        if (builder != null) {
+            ((AtomElementWriter)builder).writeTo(entry, o, mc);
+            return true;
+        }
+        return false;
+    }
+    
+    protected void createEntryContent(Entry e, Object o, Class<?> cls) throws Exception {
+    
+        Factory factory = Abdera.getNewFactory();
+        JAXBContext jc = jaxbProvider.getJAXBContext(cls, cls);
+        
+        StringWriter writer = new StringWriter();
+        jc.createMarshaller().marshal(o, writer);
+        
+        e.setContentElement(factory.newContent());
+        e.getContentElement().setContentType(Content.Type.XML);
+        e.getContentElement().setValue(writer.toString());
+        
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected void setEntryProperties(Factory factory, Entry entry, Object o, Class<?> cls) {
+        AbstractAtomElementBuilder<?> builder = atomBuilders.get(o.getClass().getName());
+        if (builder == null) {
+            return;
+        }
+        
+        setCommonElementProperties(factory, entry, builder, o);
+        
+        AbstractEntryBuilder theBuilder = (AbstractEntryBuilder)builder;
+        String author = theBuilder.getAuthor(o);
+        if (author != null) {
+            entry.addAuthor(author);
+        } else {
+            entry.addAuthor("CXF JAX-RS");
+        }
+        String title = theBuilder.getTitle(o);
+        if (title != null) {
+            entry.setTitle(title);
+        } else {
+            entry.setTitle(o.getClass().getSimpleName());
+        }
+        
+        String id = theBuilder.getId(o);
+        if (id != null) {
+            entry.setId(id);
+        } else {
+            entry.setId("uuid:" + UUID.randomUUID().toString());
+        }
+        String updated = theBuilder.getUpdated(o);
+        if (updated != null) {
+            entry.setUpdated(updated);
+        } else {
+            entry.setUpdated(new Date());
+        }
+        
+        Map<String, String> links = theBuilder.getLinks(o);
+        if (links != null) {
+            for (Map.Entry<String, String> e : links.entrySet()) {
+                entry.addLink(e.getKey(), e.getValue());
+            }
+        }
+        
+        // entry specific
+        
+        String published = theBuilder.getPublished(o);
+        if (published != null) {
+            entry.setPublished(published);    
+        }
+        
+        String summary = theBuilder.getSummary(o);
+        if (summary != null) {
+            entry.setSummary(summary);    
+        }
+        
+        List<String> terms = theBuilder.getCategories(o);
+        if (terms != null) {
+            for (String term : terms) {
+                entry.addCategory(term);
+            }
+        }
+        
+    }
+
+    @SuppressWarnings("unchecked")
+    private void setCommonElementProperties(Factory factory, ExtensibleElement element, 
+                                            AbstractAtomElementBuilder builder,
+                                            Object o) {
+        String baseUri = builder.getBaseUri(o);
+        if (baseUri != null) {
+            element.setBaseUri(baseUri);
+        }
+        
+    }
+    
+    private void reportError(String message, Exception ex) {
+        LOG.warning(message);
+        Response response = Response.status(500).type("text/plain").entity(message).build();
+        if (ex == null) {
+            throw new WebApplicationException(response);
+        } else {
+            throw new WebApplicationException(ex, response);
+        }
+    }
+    
+    private boolean isFeedRequested(MediaType mt) {
+        if ("entry".equals(mt.getParameters().get("type"))) {
+            return false;
+        }
+        return true;
+    }
+
+    public void setAtomWriters(Map<String, AtomElementWriter<?, ?>> writers) {
+        this.atomWriters = writers;
+    }
+    
+    public void setAtomReaders(Map<String, AtomElementReader<?, ?>> readers) {
+        this.atomReaders = readers;
+    }
+
+    public void setAtomBuilders(Map<String, AbstractAtomElementBuilder<?>> builders) {
+        this.atomBuilders = builders;
+    }
+
+    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, 
+                              MediaType mediaType) {
+        return true;
+    }
+
+    public Object readFrom(Class<Object> cls, Type type, Annotation[] anns, MediaType mt, 
+                           MultivaluedMap<String, String> headers, InputStream is) 
+        throws IOException, WebApplicationException {
+        boolean isFeed = isFeedRequested(mt);
+        
+        if (isFeed) {
+            return readFromFeed(cls, mt, headers, is);
+        } else {
+            Entry entry = new AtomEntryProvider().readFrom(Entry.class, Entry.class, 
+                                                           new Annotation[]{}, mt, headers, is);
+            return readFromEntry(entry, cls, mt, headers, is);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    private Object readFromFeed(Class<Object> cls, MediaType mt, 
+                                MultivaluedMap<String, String> headers, InputStream is) 
+        throws IOException {
+        
+        AtomFeedProvider p = new AtomFeedProvider();
+        Feed feed = p.readFrom(Feed.class, Feed.class, new Annotation[]{}, mt, headers, is);
+        
+        AtomElementReader<?, ?> reader = atomReaders.get(cls.getName());
+        if (reader != null) {
+            return ((AtomElementReader)reader).readFrom(feed, mc);
+        }
+        Object instance = null;
+        try {
+            String methodName = getCollectionMethod(cls, false);
+            Method m = cls.getMethod(methodName, new Class[]{List.class});
+            Class<?> realCls = InjectionUtils.getActualType(m.getGenericParameterTypes()[0]);
+            List<Object> objects = new ArrayList<Object>();
+            for (Entry e : feed.getEntries()) {
+                objects.add(readFromEntry(e, realCls, mt, headers, is));
+            }
+            instance = cls.newInstance();
+            m.invoke(instance, new Object[]{objects});
+            
+        } catch (Exception ex) {
+            reportError("Object of type " + cls.getName() + " can not be deserialized from Feed", ex);
+        }
+        return instance;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private Object readFromEntry(Entry entry, Class<?> cls, MediaType mt, 
+                                MultivaluedMap<String, String> headers, InputStream is) 
+        throws IOException {
+        
+        AtomElementReader<?, ?> reader = atomReaders.get(cls.getName());
+        if (reader != null) {
+            return ((AtomElementReader)reader).readFrom(entry, mc);
+        }
+        try {
+            Unmarshaller um = 
+                new JAXBElementProvider().getJAXBContext(cls, cls).createUnmarshaller();
+            return um.unmarshal(new StringReader(entry.getContent()));
+        } catch (Exception ex) {
+            reportError("Object of type " + cls.getName() + " can not be deserialized from Entry", ex);
+        }
+        return null;
+    }
+
+    
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/AtomPojoProvider.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/RequestDispatcherProvider.java Fri Dec  4 18:46:07 2009
@@ -41,6 +41,7 @@
 import javax.ws.rs.core.PathSegment;
 import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
 
 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.common.logging.LogUtils;
@@ -48,6 +49,7 @@
 import org.apache.cxf.transport.http.AbstractHTTPDestination;
 
 @Produces("text/html")
+@Provider
 public class RequestDispatcherProvider extends AbstractConfigurableProvider
     implements MessageBodyWriter<Object> {
     

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java Fri Dec  4 18:46:07 2009
@@ -0,0 +1,269 @@
+/**
+ * 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.jaxrs.provider;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.jaxrs.ext.atom.AbstractEntryBuilder;
+import org.apache.cxf.jaxrs.ext.atom.AbstractFeedBuilder;
+import org.apache.cxf.jaxrs.ext.atom.AtomElementReader;
+import org.apache.cxf.jaxrs.ext.atom.AtomElementWriter;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+
+public class AtomPojoProviderTest extends Assert {
+
+    private ClassPathXmlApplicationContext ctx;
+    
+    @Before
+    public void setUp() {
+        ctx = 
+            new ClassPathXmlApplicationContext(new String[] {"/org/apache/cxf/jaxrs/provider/servers.xml"});
+    }
+    
+    @Test
+    public void testWriteFeedWithBuilders() throws Exception {
+        AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom");
+        assertNotNull(provider);
+        provider.setFormattedOutput(true);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        
+        Books books = new Books();
+        List<Book> bs = new ArrayList<Book>();
+        bs.add(new Book("a"));
+        bs.add(new Book("b"));
+        books.setBooks(bs);
+        provider.writeTo(books, Books.class, Books.class, new Annotation[]{},
+                         MediaType.valueOf("application/atom+xml"), null, bos);
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Feed feed = new AtomFeedProvider().readFrom(Feed.class, null, null, null, null, bis);
+        assertEquals("Books", feed.getTitle()); 
+        List<Entry> entries = feed.getEntries();
+        assertEquals(2, entries.size());
+        verifyEntry(getEntry(entries, "a"), "a");
+        verifyEntry(getEntry(entries, "b"), "b");
+    }
+    
+    @Test
+    public void testWriteEntryWithBuilders() throws Exception {
+        AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom2");
+        assertNotNull(provider);
+        provider.setFormattedOutput(true);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        provider.writeTo(new Book("a"), Book.class, Book.class, new Annotation[]{},
+                         MediaType.valueOf("application/atom+xml;type=entry"), null, bos);
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Entry entry = new AtomEntryProvider().readFrom(Entry.class, null, null, null, null, bis);
+        verifyEntry(entry, "a");
+        
+    }
+    
+    @Test
+    public void testReadEntryWithBuilders() throws Exception {
+        AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom3");
+        assertNotNull(provider);
+        doTestReadEntry(provider);
+    }
+    
+    @Test
+    public void testReadEntryWithoutBuilders() throws Exception {
+        doTestReadEntry(new AtomPojoProvider());
+    }
+    
+    @SuppressWarnings("unchecked")
+    private void doTestReadEntry(AtomPojoProvider provider) throws Exception {
+        provider.setFormattedOutput(true);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        MediaType mt = MediaType.valueOf("application/atom+xml;type=entry");
+        provider.writeTo(new Book("a"), Book.class, Book.class, new Annotation[]{}, mt, null, bos);
+        System.out.println(bos.toString());
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Book book = (Book)provider.readFrom((Class)Book.class, Book.class, 
+                                            new Annotation[]{}, mt, null, bis);
+        assertEquals("a", book.getName());
+    }
+    
+    
+    @Test
+    public void testReadFeedWithBuilders() throws Exception {
+        AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom4");
+        assertNotNull(provider);
+        doTestReadFeed(provider);
+    }
+    
+    @Test
+    public void testReadFeedWithoutBuilders() throws Exception {
+        AtomPojoProvider provider = new AtomPojoProvider();
+        doTestReadFeed(provider);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void doTestReadFeed(AtomPojoProvider provider) throws Exception {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        MediaType mt = MediaType.valueOf("application/atom+xml;type=feed");
+        Books books = new Books();
+        List<Book> bs = new ArrayList<Book>();
+        bs.add(new Book("a"));
+        bs.add(new Book("b"));
+        books.setBooks(bs);
+        provider.writeTo(books, Books.class, Books.class, new Annotation[]{}, mt, null, bos);
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        Books books2 = (Books)provider.readFrom((Class)Books.class, Books.class, 
+                                            new Annotation[]{}, mt, null, bis);
+        List<Book> list = books2.getBooks();
+        assertEquals(2, list.size());
+        assertTrue("a".equals(list.get(0).getName()) || "a".equals(list.get(1).getName()));
+        assertTrue("b".equals(list.get(0).getName()) || "b".equals(list.get(1).getName()));        
+    }
+        
+    private Entry getEntry(List<Entry> entries, String title) {
+        for (Entry e : entries) {
+            if (title.equals(e.getTitle())) {
+                return e;
+            }
+        }
+        return null;
+    }
+    
+    private void verifyEntry(Entry e, String title) {
+        assertNotNull(e);
+        assertEquals(title, e.getTitle());
+    }
+ 
+    public static class CustomFeedWriter implements AtomElementWriter<Feed, Books> {
+
+        public void writeTo(Feed feed, Books pojoFeed, MessageContext context) {
+            feed.setTitle("Books");
+        }
+        
+    }
+    
+    public static class CustomEntryWriter implements AtomElementWriter<Entry, Book> {
+
+        public void writeTo(Entry entry, Book pojoEntry, MessageContext context) {
+            entry.setTitle(pojoEntry.getName());
+        }
+        
+    }
+    
+    public static class CustomEntryReader implements AtomElementReader<Entry, Book> {
+
+        public Book readFrom(Entry element, MessageContext mc) {
+            try {
+                String s = element.getContent();
+                                
+                Unmarshaller um = 
+                    new JAXBElementProvider().getJAXBContext(Book.class, Book.class).createUnmarshaller();
+                return (Book)um.unmarshal(new StringReader(s));
+            } catch (Exception ex) {
+                // ignore
+            }
+            return null;
+        }
+        
+    }
+    
+    public static class CustomFeedReader implements AtomElementReader<Feed, Books> {
+
+        public Books readFrom(Feed element, MessageContext mc) {
+            Books books = new Books();
+            List<Book> list = new ArrayList<Book>();
+            CustomEntryReader entryReader = new CustomEntryReader();
+            for (Entry e : element.getEntries()) {
+                list.add(entryReader.readFrom(e, mc));
+            }
+            books.setBooks(list);
+            return books;
+        }
+        
+    }
+    
+    public static class CustomFeedBuilder extends AbstractFeedBuilder<Books> {
+        @Override
+        public String getBaseUri(Books books) {
+            return "http://books";
+        }
+    }
+    
+    public static class CustomEntryBuilder extends AbstractEntryBuilder<Book> {
+        @Override
+        public String getBaseUri(Book books) {
+            return "http://book";
+        }
+    }
+    
+        
+    @XmlRootElement
+    public static class Book {
+        private String name = "Book";
+
+        public Book() {
+            
+        }
+        
+        public Book(String name) {
+            this.name = name;
+        }
+        
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+        
+        
+    }
+    
+    @XmlRootElement
+    public static class Books {
+        
+        private List<Book> books;
+        
+        public Books() {
+            
+        }
+        
+        public List<Book> getBooks() {
+            return books;
+        }
+        
+        public void setBooks(List<Book> list) {
+            books = list;
+        }
+    }
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/AtomPojoProviderTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml?rev=887317&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml Fri Dec  4 18:46:07 2009
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xmlns:util="http://www.springframework.org/schema/util"
+      xsi:schemaLocation="
+http://www.springframework.org/schema/beans 
+http://www.springframework.org/schema/beans/spring-beans.xsd
+http://www.springframework.org/schema/util 
+http://www.springframework.org/schema/util/spring-util-2.0.xsd">
+
+  <bean id="atom" class="org.apache.cxf.jaxrs.provider.AtomPojoProvider">
+    <property name="atomWriters" ref="atomWriters"/>
+    <property name="atomBuilders" ref="atomBuilders"/>
+  </bean>
+  
+  <bean id="atom2" class="org.apache.cxf.jaxrs.provider.AtomPojoProvider">
+    <property name="atomWriters" ref="atomWriters2"/>
+    <property name="atomBuilders" ref="atomBuilders2"/>
+  </bean>
+  
+  <bean id="atom3" class="org.apache.cxf.jaxrs.provider.AtomPojoProvider">
+    <property name="atomWriters" ref="atomWriters2"/>
+    <property name="atomReaders" ref="atomReaders2"/>
+  </bean>
+  
+  <bean id="atom4" class="org.apache.cxf.jaxrs.provider.AtomPojoProvider">
+    <property name="atomWriters" ref="atomWriters"/>
+    <property name="atomReaders" ref="atomReaders"/>
+  </bean>
+  
+  <util:map id="atomWriters">
+     <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Books" value-ref="feedWriter"/>
+     <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Book" value-ref="entryWriter"/>
+  </util:map>  
+  
+  <util:map id="atomWriters2">
+     <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Book" value-ref="entryWriter"/>
+  </util:map>  
+  
+  <util:map id="atomReaders">
+     <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Books" value-ref="feedReader"/>
+  </util:map>
+  
+  <util:map id="atomReaders2">
+     <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Book" value-ref="entryReader"/>
+  </util:map>
+  
+  <bean id="feedWriter" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomFeedWriter"/>
+  <bean id="entryWriter" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomEntryWriter"/>
+  <bean id="entryReader" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomEntryReader"/>
+  <bean id="feedReader" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomFeedReader"/>
+  
+  <util:map id="atomBuilders">
+    <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Books" value-ref="simpleFeedBuilder"/>
+    <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Book" value-ref="simpleEntryBuilder"/>
+  </util:map>  
+  
+  <bean id="simpleFeedBuilder" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomFeedBuilder"/>
+  
+  <util:map id="atomBuilders2">
+    <entry key="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$Book" value-ref="simpleEntryBuilder"/>
+  </util:map>  
+  
+  <bean id="simpleEntryBuilder" class="org.apache.cxf.jaxrs.provider.AtomPojoProviderTest$CustomEntryBuilder"/>
+  
+</beans>

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/provider/servers.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java Fri Dec  4 18:46:07 2009
@@ -63,6 +63,7 @@
 import org.apache.cxf.message.ExchangeImpl;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.service.model.EndpointInfo;
 import org.apache.cxf.transport.AbstractConduit;
 import org.apache.cxf.transport.Destination;
@@ -2132,9 +2133,11 @@
             }
         
             
-            if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+            if (responseCode == HttpURLConnection.HTTP_NOT_FOUND
+                && !MessageUtils.isTrue(outMessage.getContextualProperty(
+                    "org.apache.cxf.http.no_io_exceptions"))) {
                 throw new IOException("HTTP response '" + responseCode + ": " 
-                        + connection.getResponseMessage() + "'");
+                    + connection.getResponseMessage() + "'");
             }
 
             
@@ -2190,12 +2193,13 @@
                 List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
                 Cookie.handleSetCookie(sessionCookies, cookies);
             }
-
-            in = in == null
-                 ? connection.getErrorStream() == null
-                   ? connection.getInputStream()
-                   : connection.getErrorStream()
-                 : in;
+            if (responseCode != HttpURLConnection.HTTP_NOT_FOUND) {
+                in = in == null
+                     ? connection.getErrorStream() == null
+                       ? connection.getInputStream()
+                       : connection.getErrorStream()
+                     : in;
+            }
                    
             // if (in == null) : it's perfectly ok for non-soap http services
             // have no response body : those interceptors which do need it will check anyway        

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStoreSoapRestImpl.java Fri Dec  4 18:46:07 2009
@@ -29,6 +29,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.Marshaller;
 import javax.xml.ws.WebServiceContext;
@@ -85,9 +86,13 @@
                 details.setId(id);
                 throw new BookNotFoundFault(details);
             }
-            Response r = Response.status(returnCode).header("BOOK-HEADER", 
-                "No Book with id " + id + " is available").build();
-            throw new WebApplicationException(r);
+            String msg = "No Book with id " + id + " is available";
+            ResponseBuilder builder = Response.status(returnCode).header("BOOK-HEADER", msg);
+            
+            if (returnCode == 404) {
+                builder.type("text/plain").entity(msg);
+            }
+            throw new WebApplicationException(builder.build());
         }
         
         if (!invocationInProcess) {

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java?rev=887317&r1=887316&r2=887317&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java Fri Dec  4 18:46:07 2009
@@ -26,6 +26,7 @@
 import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -177,6 +178,22 @@
     }
     
     @Test
+    public void testNoBook357WebClient() throws Exception {
+        
+        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("org.apache.cxf.http.throw_io_exceptions", Boolean.TRUE);
+        bean.setProperties(properties);
+        bean.setAddress("http://localhost:9092/test/services/rest/bookstore/356");
+        WebClient wc = bean.createWebClient();
+        Response response = wc.get();
+        assertEquals(404, response.getStatus());
+        String msg = IOUtils.readStringFromStream((InputStream)response.getEntity());
+        assertEquals("No Book with id 356 is available", msg);
+        
+    }
+    
+    @Test
     public void testOtherInterceptorDrainingStream() throws Exception {
 
         String baseAddress = "http://localhost:9092/test/services/rest";



Mime
View raw message