| /* |
| * 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 feed; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.net.Socket; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.List; |
| |
| import junit.framework.Assert; |
| |
| import org.apache.abdera.Abdera; |
| import org.apache.abdera.model.Base; |
| import org.apache.abdera.model.Collection; |
| import org.apache.abdera.model.Document; |
| import org.apache.abdera.model.Entry; |
| import org.apache.abdera.model.Feed; |
| import org.apache.abdera.parser.Parser; |
| 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.writer.Writer; |
| import org.apache.abdera.writer.WriterFactory; |
| import org.apache.tuscany.sca.host.embedded.SCADomain; |
| import org.junit.AfterClass; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| /** |
| * Tests use of server provided feed entity tags for Atom binding in Tuscany. |
| * Tests conditional gets (e.g. get if-none-match) or conditional posts (post |
| * if-match) using entity tags and last modified entries in headers. Uses the |
| * SCA provided Provider composite to act as a server. Uses the Abdera provided |
| * Client to act as a client. |
| */ |
| public class FeedAggregatorTestCase { |
| public final static String providerURI = "http://localhost:8083/atomAggregator"; |
| protected static SCADomain scaProviderDomain; |
| protected static Abdera abdera; |
| protected static AbderaClient client; |
| protected static Parser abderaParser; |
| protected static String eTag; |
| protected static Date lastModified; |
| protected static long contentLength; |
| protected static int numberEntries; |
| protected static final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z"); // RFC822 date time |
| |
| @BeforeClass |
| public static void init() throws Exception { |
| if (!internetConnected()) { |
| // no internet connection |
| return; |
| } |
| try { |
| System.out.println(">>>FeedAggregatorTest.init"); |
| scaProviderDomain = SCADomain.newInstance("FeedAggregator.composite"); |
| abdera = new Abdera(); |
| client = new AbderaClient(abdera); |
| abderaParser = Abdera.getNewParser(); |
| } catch (Throwable e) { |
| System.out.println(e); |
| e.printStackTrace(); |
| } |
| } |
| |
| @AfterClass |
| public static void destroy() throws Exception { |
| System.out.println(">>>FeedAggregatorTest.destroy"); |
| if (scaProviderDomain != null) { |
| scaProviderDomain.close(); |
| } |
| } |
| |
| @Test |
| public void testPrelim() throws Exception { |
| if (scaProviderDomain == null) { |
| // no internet connection |
| return; |
| } |
| Assert.assertNotNull(scaProviderDomain); |
| Assert.assertNotNull(client); |
| } |
| |
| @Test |
| public void testFeedBasics() throws Exception { |
| if (scaProviderDomain == null) { |
| // no internet connection |
| return; |
| } |
| System.out.println(">>>FeedAggregatorTest.testFeedBasics"); |
| RequestOptions opts = new RequestOptions(); |
| // Normal feed request |
| ClientResponse res = client.get(providerURI, opts); |
| Assert.assertNotNull(res); |
| try { |
| // Assert feed provided since no predicates |
| Assert.assertEquals(200, res.getStatus()); |
| Assert.assertEquals(ResponseType.SUCCESS, res.getType()); |
| // AtomTestCaseUtils.printResponseHeaders( "Feed response headers:", |
| // " ", res ); |
| |
| // Perform other tests on feed. |
| contentLength = getContentLength(res); |
| System.out.println("FeedAggregatorTest.testFeedBasics full contentLength=" + contentLength); |
| |
| Document<Feed> doc = res.getDocument(); |
| Assert.assertNotNull(doc); |
| Feed feed = doc.getRoot(); |
| Assert.assertNotNull(feed); |
| |
| // printFeed( "Feed values", " ", feed ); |
| // RFC 4287 requires non-null id, title, updated elements |
| Assert.assertNotNull(feed.getId()); |
| Assert.assertNotNull(feed.getTitle()); |
| Assert.assertNotNull(feed.getUpdated()); |
| |
| eTag = res.getHeader("ETag"); |
| Assert.assertNotNull(eTag); |
| lastModified = res.getLastModified(); |
| Assert.assertNotNull(lastModified); |
| |
| numberEntries = getEntryCount(feed); |
| System.out.println("FeedAggregatorTest.testFeedBasics number entries=" + numberEntries); |
| |
| // printFeed( "Aggregated Feed Contents:", " ", feed ); |
| // System.out.println( "FeedAggregatorTest.testFeedBasics feed=" + |
| // feed ); |
| // printResponseHeaders( "Aggregated Feed response headers:", " ", |
| // res ); |
| // System.out.println("Aggregated Feed response body:"); |
| // prettyPrint(abdera, res.getDocument()); |
| // printEntryUpdates( "Aggregated Feed feed updates", " ", feed ); |
| } finally { |
| res.release(); |
| } |
| } |
| |
| @Test |
| public void testUnmodifiedGetIfModified() throws Exception { |
| if (scaProviderDomain == null) { |
| // no internet connection |
| return; |
| } |
| System.out.println(">>>FeedAggregatorTest.testFeedUnmodifiedGetIfModified"); |
| // Feed request with predicates |
| RequestOptions opts = new RequestOptions(); |
| final String contentType = "application/atom+xml"; |
| opts.setContentType(contentType); |
| opts.setHeader("If-Modified-Since", dateFormat.format(new Date(0))); |
| |
| ClientResponse res = client.get(providerURI, opts); |
| Assert.assertNotNull(res); |
| try { |
| // Should return 200 - Feed provided since feed is changed. |
| Assert.assertEquals(200, res.getStatus()); |
| Assert.assertEquals(ResponseType.SUCCESS, res.getType()); |
| |
| String thisETag = res.getHeader("ETag"); |
| Assert.assertNotNull(thisETag); |
| Date thisLastModified = res.getLastModified(); |
| Assert.assertNotNull(thisLastModified); |
| |
| // Entry count and body size should be equal to basic request |
| long thisContentLength = getContentLength(res); |
| |
| Document<Feed> doc = res.getDocument(); |
| Assert.assertNotNull(doc); |
| Feed feed = doc.getRoot(); |
| Assert.assertNotNull(feed); |
| int thisNumberEntries = getEntryCount(feed); |
| // System.out.println( |
| // "FeedAggregatorTest.UnmodifiedGetIfModified number entries=" + |
| // numberEntries + ", this number entries=" + thisNumberEntries ) ; |
| } finally { |
| res.release(); |
| } |
| } |
| |
| @Test |
| public void testUnmodifiedGetIfUnModified() throws Exception { |
| if (scaProviderDomain == null) { |
| // no internet connection |
| return; |
| } |
| System.out.println(">>>FeedAggregatorTest.testFeedUnmodifiedGetIfUnModified"); |
| // Feed request with predicates |
| RequestOptions opts = new RequestOptions(); |
| final String contentType = "application/atom+xml"; |
| opts.setContentType(contentType); |
| opts.setHeader("If-Unmodified-Since", dateFormat.format(new Date(0))); |
| |
| ClientResponse res = client.get(providerURI, opts); |
| Assert.assertNotNull(res); |
| try { |
| // Should return 412 - Feed not provided since feed is modified |
| // since. |
| Assert.assertEquals(412, res.getStatus()); |
| |
| // Entry count and body size should be equal to basic request |
| long thisContentLength = getContentLength(res); |
| System.out |
| .println("FeedAggregatorTest.UnModifiedGetIfUnModified saved " + (contentLength - thisContentLength) |
| + " bytes of network traffic due to caching."); |
| } finally { |
| res.release(); |
| } |
| } |
| |
| /** Print feed vital fields. */ |
| public static void printFeed(String title, String indent, Feed feed) { |
| if (feed == null) { |
| System.out.println(title + " feed is null"); |
| return; |
| } |
| |
| System.out.println(title); |
| System.out.println(indent + "id=" + feed.getId()); |
| System.out.println(indent + "title=" + feed.getTitle()); |
| System.out.println(indent + "updated=" + feed.getUpdated()); |
| System.out.println(indent + "author=" + feed.getAuthor()); |
| System.out.println(indent + "self link=" + feed.getSelfLink()); |
| Collection collection = feed.getCollection(); |
| if (collection == null) { |
| System.out.println(indent + "collection=null"); |
| } else { |
| System.out.println(indent + "collection=" + collection); |
| } |
| } |
| |
| /* Print headers of request. */ |
| public static void printRequestHeaders(String title, String indent, RequestOptions request) { |
| System.out.println(title); |
| if (request == null) { |
| System.out.println(indent + " request is null"); |
| return; |
| } |
| String[] headerNames = request.getHeaderNames(); |
| for (String headerName : headerNames) { |
| String header = request.getHeader(headerName); |
| System.out.println(indent + " header name,value=" + headerName + "," + header); |
| } |
| } |
| |
| /* Print headers of response. */ |
| public static void printResponseHeaders(String title, String indent, ClientResponse response) { |
| System.out.println(title); |
| if (response == null) { |
| System.out.println(indent + " response is null"); |
| return; |
| } |
| String[] headerNames = response.getHeaderNames(); |
| for (String headerName : headerNames) { |
| String header = response.getHeader(headerName); |
| System.out.println(indent + " header name,value=" + headerName + "," + header); |
| } |
| |
| } |
| |
| /** Pretty print the document body. */ |
| public static void prettyPrint(Abdera abdera, Base doc) throws IOException { |
| WriterFactory factory = abdera.getWriterFactory(); |
| Writer writer = factory.getWriter("prettyxml"); |
| writer.writeTo(doc, System.out); |
| System.out.println(); |
| } |
| |
| /** Print the updated elements of the feed entries. */ |
| public static void printEntryUpdates(String title, String indent, Feed feed) { |
| if (feed == null) { |
| System.out.println(title + " feed is null"); |
| return; |
| } |
| |
| System.out.println(title); |
| List<Entry> entries = feed.getEntries(); |
| if (entries == null) { |
| System.out.println(indent + " null entries"); |
| } |
| System.out.println(indent + "entries size=" + entries.size()); |
| |
| int i = 0; |
| for (Entry entry : entries) { |
| String entryTitle = entry.getTitle(); |
| if ((entryTitle != null) && (entryTitle.length() > 20)) |
| entryTitle = entryTitle.substring(0, 20); |
| // System.out.println( indent + i++ + ": title=\"" + entryTitle + |
| // "\", updated=" + entry.getUpdated() + ", published=" + |
| // entry.getPublished() ); |
| System.out.println(indent + i++ + ": title=\"" + entryTitle + "\", updated=" + entry.getUpdated()); |
| } |
| } |
| |
| /** Get the length of the response body content. */ |
| public static long getContentLength(ClientResponse response) { |
| // getContentLenght returns -1 |
| // contentLength = response.getContentLength(); |
| try { |
| Reader reader = response.getReader(); |
| long actualSkip = reader.skip(Long.MAX_VALUE); |
| return actualSkip; |
| } catch (IOException e) { |
| } |
| return -1L; |
| } |
| |
| /** Get a count of entries in the feed. */ |
| public static int getEntryCount(Feed feed) { |
| if (feed == null) { |
| return 0; |
| } |
| |
| List<Entry> entries = feed.getEntries(); |
| if (entries == null) { |
| return 0; |
| } |
| return entries.size(); |
| } |
| |
| /** |
| * Given a feed, determine the median point of the entries. Use the updated |
| * field of the entries to determine median. |
| * |
| * @param feed |
| * @return |
| */ |
| public static Date getUpdatedMedian(Feed feed) { |
| Date sentinal = null; |
| if (feed == null) { |
| return sentinal; |
| } |
| |
| List<Entry> entries = feed.getEntries(); |
| if (entries == null) { |
| return sentinal; |
| } |
| int size = entries.size(); |
| if (size == 0) { |
| return sentinal; |
| } |
| // System.out.println( "getUpdatedMedian entries size=" + |
| // entries.size()); |
| ArrayList<Date> updates = new ArrayList<Date>(size); |
| |
| for (Entry entry : entries) { |
| Date entryUpdated = entry.getUpdated(); |
| if (entryUpdated == null) { |
| entryUpdated = new Date(0); |
| } |
| updates.add(entryUpdated); |
| } |
| Collections.sort(updates); |
| // System.out.println( "getUpdatedMedian entry min update=" + |
| // updates.get( 0 )); |
| // System.out.println( "getUpdatedMedian entry max update=" + |
| // updates.get( size - 1 )); |
| Date median = updates.get(size / 2); |
| // System.out.println( "getUpdatedMedian entry max median=" + median ); |
| return median; |
| } |
| |
| private static boolean internetConnected() { |
| try { |
| // see whether an internet connection is available |
| Socket testInternet = new Socket("tuscany.apache.org", 80); |
| testInternet.close(); |
| |
| // internet connection available |
| return true; |
| |
| } catch (Exception e) { |
| // no internet connection |
| System.out.println("Unable to run test because no internet connection available"); |
| return false; |
| } |
| } |
| } |