blob: 3ee44c4c0e3953ba3d1e4702f61f48e412c38baf [file] [log] [blame]
/*
* 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;
}
}
}