Author: antelder
Date: Wed Aug 13 04:18:32 2008
New Revision: 685516

URL: http://svn.apache.org/viewvc?rev=685516&view=rev
Log:
TUSCANY-2504: apply patch from Dan Becker to give Atom binding support for 
negotiated content types

Added:
    
tuscany/java/sca/modules/binding-atom-abdera/src/test/java/org/apache/tuscany/sca/binding/atom/ContentNegotiationTest.java
Modified:
    tuscany/java/sca/modules/binding-atom-abdera/pom.xml
    
tuscany/java/sca/modules/binding-atom-abdera/src/main/java/org/apache/tuscany/sca/binding/atom/provider/AtomBindingListenerServlet.java

Modified: tuscany/java/sca/modules/binding-atom-abdera/pom.xml
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/binding-atom-abdera/pom.xml?rev=685516&r1=685515&r2=685516&view=diff
==============================================================================
--- tuscany/java/sca/modules/binding-atom-abdera/pom.xml (original)
+++ tuscany/java/sca/modules/binding-atom-abdera/pom.xml Wed Aug 13 04:18:32 
2008
@@ -113,6 +113,18 @@
         </dependency>            
                 
         <dependency>
+            <groupId>org.apache.abdera</groupId>
+            <artifactId>abdera-extensions-main</artifactId>
+            <version>0.4.0-incubating</version> 
+        </dependency>            
+                
+        <dependency>
+            <groupId>org.apache.abdera</groupId>
+            <artifactId>abdera-extensions-json</artifactId>
+            <version>0.4.0-incubating</version> 
+        </dependency>            
+                
+        <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
             <version>2.4</version> 

Modified: 
tuscany/java/sca/modules/binding-atom-abdera/src/main/java/org/apache/tuscany/sca/binding/atom/provider/AtomBindingListenerServlet.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/binding-atom-abdera/src/main/java/org/apache/tuscany/sca/binding/atom/provider/AtomBindingListenerServlet.java?rev=685516&r1=685515&r2=685516&view=diff
==============================================================================
--- 
tuscany/java/sca/modules/binding-atom-abdera/src/main/java/org/apache/tuscany/sca/binding/atom/provider/AtomBindingListenerServlet.java
 (original)
+++ 
tuscany/java/sca/modules/binding-atom-abdera/src/main/java/org/apache/tuscany/sca/binding/atom/provider/AtomBindingListenerServlet.java
 Wed Aug 13 04:18:32 2008
@@ -48,12 +48,14 @@
 import org.apache.abdera.model.Workspace;
 import org.apache.abdera.parser.ParseException;
 import org.apache.abdera.parser.Parser;
+import org.apache.abdera.writer.WriterFactory;
+
 import org.apache.commons.codec.binary.Base64;
 import org.apache.tuscany.sca.data.collection.Entry;
 import org.apache.tuscany.sca.databinding.Mediator;
 import org.apache.tuscany.sca.interfacedef.DataType;
-import org.apache.tuscany.sca.interfacedef.Operation;
 import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.Operation;
 import org.apache.tuscany.sca.interfacedef.util.XMLType;
 import org.apache.tuscany.sca.invocation.InvocationChain;
 import org.apache.tuscany.sca.invocation.Invoker;
@@ -318,18 +320,35 @@
                                }
                        }
                 }
-                
-                // Write the Atom feed
-                response.setContentType("application/atom+xml; charset=utf-8");
-                // Provide Etag based on Id and time.               
-                response.addHeader(ETAG, feedETag );
-                if ( feedUpdated != null )
-                   response.addHeader(LASTMODIFIED, dateFormat.format( 
feedUpdated ));
-                try {
-                         
feed.getDocument().writeTo(response.getOutputStream());
-                } catch (IOException ioe) {
-                    throw new ServletException(ioe);
-                }
+                // Content negotiation
+               String acceptType = request.getHeader( "Accept" );
+               String preferredType = getContentPreference( acceptType ); 
+               if (( preferredType != null ) && ((preferredType.indexOf( 
"json") > -1) || (preferredType.indexOf( "JSON") > -1 ))) {
+                       // JSON response body
+                    response.setContentType("application/json;type=feed");
+                    
+                    try {
+                               Abdera abdera = new Abdera();
+                               WriterFactory wf = abdera.getWriterFactory();
+                               org.apache.abdera.writer.Writer json = 
wf.getWriter("json");
+                       feed.writeTo(json, response.getWriter());
+                    } catch (Exception e) {
+                        throw new ServletException(e);
+                    }                          
+
+               } else {
+                       // Write the Atom feed
+                       
response.setContentType("application/atom+xml;type=feed");
+                       // Provide Etag based on Id and time.               
+                       response.addHeader(ETAG, feedETag );
+                       if ( feedUpdated != null )
+                               response.addHeader(LASTMODIFIED, 
dateFormat.format( feedUpdated ));
+                       try {
+                               
feed.getDocument().writeTo(response.getOutputStream());
+                       } catch (IOException ioe) {
+                               throw new ServletException(ioe);
+                       }
+               }
             } else {
                 response.sendError(HttpServletResponse.SC_NOT_FOUND);
             }
@@ -374,12 +393,30 @@
                       response.addHeader(LOCATION, link.getHref().toString());
                    }
                 }
-                response.setContentType("application/atom+xml;type=entry");
-                try {
-                        feedEntry.writeTo(getWriter(response));
-                } catch (IOException ioe) {
-                    throw new ServletException(ioe);
-                }
+
+                // Content negotiation
+                String acceptType = request.getHeader( "Accept" );
+               String preferredType = getContentPreference( acceptType ); 
+               if (( preferredType != null ) && ((preferredType.indexOf( 
"json") > -1) || (preferredType.indexOf( "JSON") > -1 ))) {
+                       // JSON response body
+                    response.setContentType("application/json;type=entry");
+                    try {
+                               Abdera abdera = new Abdera();
+                               WriterFactory wf = abdera.getWriterFactory();
+                               org.apache.abdera.writer.Writer json = 
wf.getWriter("json");
+                       feedEntry.writeTo(json, response.getWriter());
+                    } catch (Exception e) {
+                        throw new ServletException(e);
+                    }                          
+               } else {
+                       // XML response body 
+                       
response.setContentType("application/atom+xml;type=entry");
+                       try {
+                               feedEntry.writeTo(getWriter(response));
+                       } catch (IOException ioe) {
+                               throw new ServletException(ioe);
+                       }
+               }
             } else {
                 response.sendError(HttpServletResponse.SC_NOT_FOUND);
             }
@@ -710,4 +747,14 @@
         
         return feedId + "-" + feedUpdated.hashCode();
     }
+
+    public static String getContentPreference( String acceptType ) {
+       if (( acceptType == null ) || ( acceptType.length() < 1 )) {
+            return "application/atom+xml";             
+       }
+       StringTokenizer st = new StringTokenizer( acceptType, "," );
+       if ( st.hasMoreTokens() )
+               return st.nextToken();                  
+        return "application/atom+xml";
+    }
 }

Added: 
tuscany/java/sca/modules/binding-atom-abdera/src/test/java/org/apache/tuscany/sca/binding/atom/ContentNegotiationTest.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/binding-atom-abdera/src/test/java/org/apache/tuscany/sca/binding/atom/ContentNegotiationTest.java?rev=685516&view=auto
==============================================================================
--- 
tuscany/java/sca/modules/binding-atom-abdera/src/test/java/org/apache/tuscany/sca/binding/atom/ContentNegotiationTest.java
 (added)
+++ 
tuscany/java/sca/modules/binding-atom-abdera/src/test/java/org/apache/tuscany/sca/binding/atom/ContentNegotiationTest.java
 Wed Aug 13 04:18:32 2008
@@ -0,0 +1,249 @@
+/*
+ * 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.tuscany.sca.binding.atom;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import junit.framework.Assert;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.tuscany.sca.binding.atom.collection.Collection;
+import org.apache.tuscany.sca.host.embedded.SCADomain;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Base;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Service;
+import org.apache.abdera.protocol.Response.ResponseType;
+import org.apache.abdera.protocol.client.AbderaClient;
+import org.apache.abdera.protocol.client.ClientResponse;
+import org.apache.abdera.protocol.client.RequestOptions;
+import org.apache.abdera.protocol.client.util.BaseRequestEntity;
+import org.apache.abdera.util.EntityTag;
+import org.apache.abdera.parser.Parser;
+
+
+/**
+ * Tests use of content negotiation for Atom binding in Tuscany.
+ * Uses the SCA provided Provider composite to act as a server.
+ * Uses the Abdera provided Client to act as a client.
+ */
+public class ContentNegotiationTest {
+       public final static String providerURI = 
"http://localhost:8084/customer";;
+       protected static SCADomain scaProviderDomain;
+       protected static CustomerClient testService;
+    protected static Abdera abdera;
+    protected static AbderaClient client;
+    protected static Parser abderaParser;    
+    protected static String lastId;
+
+       @BeforeClass
+       public static void init() throws Exception {
+               System.out.println(">>>ContentNegotiationTest.init");
+               scaProviderDomain = 
SCADomain.newInstance("org/apache/tuscany/sca/binding/atom/Provider.composite");
+               abdera = new Abdera();
+               client = new AbderaClient(abdera);
+               abderaParser = Abdera.getNewParser();
+       }
+
+       @AfterClass
+       public static void destroy() throws Exception {
+               System.out.println(">>>ContentNegotiationTest.destroy");
+               scaProviderDomain.close();
+       }
+
+       @Test
+       public void testPrelim() throws Exception {
+               Assert.assertNotNull(scaProviderDomain);
+               Assert.assertNotNull( client );
+       }
+       
+    @Test
+       public void testPost() throws Exception {
+               System.out.println(">>>ContentNegotiationTest.testPost");
+               // Testing of entry creation
+               Factory factory = abdera.getFactory();
+               String customerName = "Fred Farkle";
+               Entry entry = factory.newEntry();
+               entry.setTitle("customer " + customerName);
+               entry.setUpdated(new Date());
+               entry.addAuthor("Apache Tuscany");
+               // ID created by collection.
+               Content content = abdera.getFactory().newContent();
+               content.setContentType(Content.Type.TEXT);
+               content.setValue(customerName);
+               entry.setContentElement(content);
+
+               RequestOptions opts = new RequestOptions();
+               final String contentType = "application/atom+xml; type=entry"; 
+               opts.setContentType(contentType);
+               // AtomTestCaseUtils.printRequestHeaders( "Post request 
headers", "   ", opts );
+               IRI colUri = new IRI(providerURI).resolve("customer");
+               // res = client.post(colUri.toString() + "?test=foo", entry, 
opts);
+               ClientResponse res = client.post(colUri.toString(), entry, 
opts);
+               
+           // Assert response status code is 201-OK.
+               // Assert response header Content-Type: application/atom+xml; 
charset=UTF-8
+       Assert.assertEquals(201, res.getStatus());
+       String returnedContentType = res.getContentType().toString().trim();
+       Assert.assertEquals(contentType, returnedContentType );
+
+       String eTag = res.getHeader( "ETag" );
+       if ( eTag != null)
+               lastId = eTag.substring( 1, eTag.length()-1);
+       
+       // AtomTestCaseUtils.printResponseHeaders( "Entry post response 
headers:", "   ", res );
+       // System.out.println("Entry post response content:");
+       // AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());
+       }
+
+       @Test
+       public void testXMLEntryGet() throws Exception {
+               System.out.println(">>>ContentNegotiationTest.testXMLEntryGet");
+               RequestOptions opts = new RequestOptions();
+               opts.setHeader( "Accept", "application/atom+xml" );
+               
+               IRI colUri = new IRI(providerURI).resolve("customer");
+               ClientResponse res = client.get(colUri.toString() + "/" + 
lastId, opts);
+       Assert.assertEquals(200, res.getStatus());
+       String returnedContentType = res.getContentType().toString().trim();
+       // Assert.assertEquals(contentType, returnedContentType );
+               res.release();      
+       }
+
+       @Test
+       public void testJSONEntryGet() throws Exception {
+               
System.out.println(">>>ContentNegotiationTest.testJSONEntryGet");
+               RequestOptions opts = new RequestOptions();
+               opts.setHeader( "Accept", "application/json" );
+               
+               IRI colUri = new IRI(providerURI).resolve("customer");
+               ClientResponse res = client.get(colUri.toString() + "/" + 
lastId, opts);
+               try {
+                       Assert.assertEquals(200, res.getStatus());
+                       // Abdera 0.4 throws exception on getContentType with 
application/json.         
+                       // System.out.println( 
"ContentNegotiationTest.testJSONEntryGet contentType=" + res.getContentType());
+                       String contentType = res.getHeader( "Content-Type");
+                       Assert.assertTrue( -1 < contentType.indexOf( 
"application/json" ));
+                       // Following is a poor man's JSONObject test to avoid 
dependency on JSON libs.
+                       // JSONObject jsonResp = new JSONObject(res.);
+                       // Assert.assertEquals(12345, 
jsonResp.getInt("result"));
+                       String responseBody = readResponse( res.getReader() );
+                       Assert.assertTrue( responseBody.startsWith( "{") );
+                       Assert.assertTrue( responseBody.endsWith( "}") );
+                       Assert.assertTrue( -1 < responseBody.indexOf( "\"id\"" 
));
+                       Assert.assertTrue( -1 < responseBody.indexOf( 
"\"title\"" ));
+                       Assert.assertTrue( -1 < responseBody.indexOf( 
"\"updated\"" ));
+                       // AtomTestCaseUtils.printResponseHeaders( "JSON Entry 
response headers:", "   ", res );
+                       // System.out.println( 
"ContentNegotiationTest.testJSONEntryGet JSON entry body=" + responseBody );
+               } finally {
+                       res.release();                          
+               }
+       }
+
+       @Test
+    public void testXMLFeedGet() throws Exception {            
+               System.out.println(">>>ContentNegotiationTest.testXMLFeedGet");
+               RequestOptions opts = new RequestOptions();
+               opts.setHeader( "Accept", "application/atom+xml" );
+               
+               // Atom feed request
+               ClientResponse res = client.get(providerURI, opts);
+               Assert.assertNotNull(res);
+               try {
+                       // Asser feed provided since no predicates
+                       Assert.assertEquals(200, res.getStatus());
+                       Assert.assertEquals(ResponseType.SUCCESS, 
res.getType());
+               // AtomTestCaseUtils.printResponseHeaders( "Feed response 
headers:", "   ", res );
+               // System.out.println("Feed response content:");
+               // AtomTestCaseUtils.prettyPrint(abdera, res.getDocument());
+
+               // Perform other tests on feed.
+                       Document<Feed> doc = res.getDocument();
+                       Assert.assertNotNull( doc );
+                       Feed feed = doc.getRoot();
+                       Assert.assertNotNull( feed );
+                       // RFC 4287 requires non-null id, title, updated 
elements
+                       Assert.assertNotNull( feed.getId() );
+                       Assert.assertNotNull( feed.getTitle() );
+                       Assert.assertNotNull( feed.getUpdated() );
+                       // AtomTestCaseUtils.printFeed( "Feed values", "   ", 
feed );
+               } finally {
+                       res.release();
+               }
+       }               
+
+       @Test
+    public void testJSONFeedGet() throws Exception {           
+               System.out.println(">>>ContentNegotiationTest.testJSONFeedGet");
+               RequestOptions opts = new RequestOptions();
+               opts.setHeader( "Accept", "application/json" );
+               
+               // JSON feed request
+               ClientResponse res = client.get(providerURI, opts);
+               Assert.assertNotNull(res);
+               try {
+                       // Assert feed provided since no predicates
+                       Assert.assertEquals(200, res.getStatus());
+                       // Abdera 0.4 throws exception on getContentType with 
application/json.         
+                       // System.out.println( 
"ContentNegotiationTest.testJSONEntryGet contentType=" + res.getContentType());
+                       String contentType = res.getHeader( "Content-Type");
+                       Assert.assertTrue( -1 < contentType.indexOf( 
"application/json" ));
+                       // Following is a poor man's JSONObject test to avoid 
dependency on JSON libs.
+                       // JSONObject jsonResp = new JSONObject(res.);
+                       // Assert.assertEquals(12345, 
jsonResp.getInt("result"));
+                       String responseBody = readResponse( res.getReader() );
+                       Assert.assertTrue( responseBody.startsWith( "{") );
+                       Assert.assertTrue( responseBody.endsWith( "}") );
+                       Assert.assertTrue( -1 < responseBody.indexOf( "\"id\"" 
));
+                       Assert.assertTrue( -1 < responseBody.indexOf( 
"\"title\"" ));
+                       Assert.assertTrue( -1 < responseBody.indexOf( 
"\"updated\"" ));
+                       Assert.assertTrue( -1 < responseBody.indexOf( 
"\"entries\"" ));
+                       // AtomTestCaseUtils.printResponseHeaders( "JSON Entry 
response headers:", "   ", res );
+                       // System.out.println( 
"ContentNegotiationTest.testJSONEntryGet JSON entry body=" + responseBody );
+               } finally {
+                       res.release();
+               }
+       }
+       
+       protected String readResponse( Reader responseReader ) {
+               if ( responseReader == null ) return ""; 
+               StringBuffer sb = new StringBuffer(1024);
+               try {
+                       int charValue = 0;
+                       while ((charValue = responseReader.read()) != -1) {
+                               //result = result + (char) charValue;
+                               sb.append((char)charValue);
+                       }
+               } catch ( IOException e ) {
+               }
+               return sb.toString();
+       }
+}


Reply via email to