diff --git a/utilities/testContentNegotiation/build.xml b/utilities/testContentNegotiation/build.xml
new file mode 100644
index 000000000..34fdad5b2
--- /dev/null
+++ b/utilities/testContentNegotiation/build.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+clean - Delete all artifacts so the next build will be from scratch.
+compile - Compile the Java source files.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/utilities/testContentNegotiation/readme.md b/utilities/testContentNegotiation/readme.md
new file mode 100644
index 000000000..a7c81d543
--- /dev/null
+++ b/utilities/testContentNegotiation/readme.md
@@ -0,0 +1 @@
+This directory contains a simple java utility to test of content neogation of a running VIVO instance.
diff --git a/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java b/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java
new file mode 100644
index 000000000..d2ff5a112
--- /dev/null
+++ b/utilities/testContentNegotiation/src/edu/cornell/mannlib/vitro/testContentNegotiation/TestContentNegotiation.java
@@ -0,0 +1,231 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.testContentNegotiation;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+
+
+import org.apache.http.NameValuePair;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+
+/**
+ * Utility to test content negotiation of some features
+ * of a running vivo instance.
+ *
+ * usage:
+ * java -cp $YOUR_CP edu.cornell.mannlib.vitro.testContentNegotiation VIVOURL email password
+ *
+ * This will return 0 and print "testContentNegotiation: Content negotiation tests passed.\n"
+ * on success.
+ * It will return 1 and print errors to STDOUT on failure.
+ */
+public class TestContentNegotiation{
+
+ static CNTest[] tests = {
+ //URL, QUERY, Accept header, pattern for response Content-Type, pattern for body, description
+ new CNTest(constants.servlet, constants.query, "none", ".*", ".*","Test to see if a basic request works")
+ };
+
+
+ public static void main(String[] argv){
+
+ if( argv.length != 3 ){
+ doHelp();
+ System.exit(2);
+ }
+
+ String baseUrl = argv[0];
+ String email = argv[1];
+ String pw = argv[2];
+
+ List errors = new ArrayList();
+
+ for( CNTest test : tests ){
+ String msg = test.doTest( baseUrl, email, pw);
+ if( msg != null )
+ errors.add( msg );
+ }
+
+ if( errors.isEmpty() ){
+ System.out.println("testContentNegotiation: Content negotiation tests passed.\n");
+ System.exit(0);
+ }else{
+ doErrors( errors );
+ System.exit(1);
+ }
+ }
+
+ private static void doErrors( List errors){
+ System.out.println("ERROR testContentNegotiation: There were " + errors.size() + " errors.");
+ for( String err : errors){
+ System.out.println( err );
+ }
+ }
+
+ private static void doHelp(){
+ System.out.println(
+ "Utility to test content negotiation of some features \n" +
+ "of a running vivo instance. \n" +
+ "usage: \n" +
+ "java -cp $YOUR_CP edu.cornell.mannlib.vitro.testContentNegotiation VIVOURL email password\n");
+ }
+
+ protected static class CNTest{
+ String request;
+ String acceptHeader;
+ String query;
+ Pattern expectedResponseContentType;
+ Pattern expectedBody;
+ String description;
+
+ public CNTest(String request, String query, String acceptHeader,
+ String expectedResponseContentType, String expectedBody,
+ String description){
+ this.request = request;
+ this.acceptHeader = acceptHeader;
+ this.query = query;
+ this.expectedResponseContentType = Pattern.compile( expectedResponseContentType );
+ this.expectedBody = Pattern.compile( expectedBody );
+ this.description = description;
+ }
+
+ /**
+ * Returns a non-null string on failure.
+ * Returns null on success.
+ */
+ String doTest(String baseUrl, String email, String pw) {
+ HttpClient httpClient = new DefaultHttpClient();
+ HttpPost httpPost = new HttpPost( baseUrl + request );
+ httpPost.addHeader("Accept", acceptHeader);
+ List nvps = new ArrayList ();
+ nvps.add(new BasicNameValuePair("email", "vip"));
+ nvps.add(new BasicNameValuePair("password", "secret"));
+ nvps.add(new BasicNameValuePair("query", query));
+ try {
+ httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+ } catch (UnsupportedEncodingException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ HttpResponse resp;
+ try {
+ resp = httpClient.execute(httpPost);
+ } catch (Exception e){
+ return "Failed, exception, " + e.getMessage() ;
+ }
+
+ //Check response content type
+ try{
+ Header[] contentType = resp.getHeaders("Content-Type");
+ if( contentType == null || contentType.length == 0 ){
+ return "Failed, Content-Type was empty be expected " + expectedResponseContentType;
+ }
+
+ boolean foundMatch = false;
+ for( Header header : contentType){
+ Matcher m = expectedResponseContentType.matcher( header.getValue() );
+ if( m.matches() ){
+ foundMatch = true;
+ break;
+ }
+ }
+
+ if( !foundMatch ){
+ return "Failed to match expected Content-Type " +
+ expectedResponseContentType.toString() +
+ " to value " + resp.getHeaders("Content-Type") ;
+ }
+ }finally{
+ httpPost.releaseConnection();
+ }
+
+ //TODO: Check body
+ return null;
+ }
+ }
+
+
+ protected static class constants{
+
+ static String servlet = "/admin/sparqlquery";
+
+ static String query =
+ "PREFIX rdf: \n" +
+ "PREFIX rdfs: \n" +
+ "PREFIX xsd: \n" +
+ "PREFIX owl: \n" +
+ "PREFIX swrl: \n" +
+ "PREFIX swrlb: \n" +
+ "PREFIX vitro: \n" +
+ "PREFIX p.1: \n" +
+ "PREFIX p.2: \n" +
+ "PREFIX bibo: \n" +
+ "PREFIX c4o: \n" +
+ "PREFIX p.3: \n" +
+ "PREFIX p.4: \n" +
+ "PREFIX p.5: \n" +
+ "PREFIX p.6: \n" +
+ "PREFIX p.7: \n" +
+ "PREFIX p.8: \n" +
+ "PREFIX p.9: \n" +
+ "PREFIX dcelem: \n" +
+ "PREFIX dcterms: \n" +
+ "PREFIX p.10: \n" +
+ "PREFIX p.11: \n" +
+ "PREFIX event: \n" +
+ "PREFIX foaf: \n" +
+ "PREFIX fabio: \n" +
+ "PREFIX geo: \n" +
+ "PREFIX p.12: \n" +
+ "PREFIX p.13: \n" +
+ "PREFIX p.14: \n" +
+ "PREFIX p.15: \n" +
+ "PREFIX p.16: \n" +
+ "PREFIX p.17: \n" +
+ "PREFIX p.18: \n" +
+ "PREFIX pvs: \n" +
+ "PREFIX p.19: \n" +
+ "PREFIX p.20: \n" +
+ "PREFIX p.21: \n" +
+ "PREFIX p.22: \n" +
+ "PREFIX p.23: \n" +
+ "PREFIX ero: \n" +
+ "PREFIX p.24: \n" +
+ "PREFIX scires: \n" +
+ "PREFIX p.25: \n" +
+ "PREFIX skos: \n" +
+ "PREFIX p.26: \n" +
+ "PREFIX p.27: \n" +
+ "PREFIX p.28: \n" +
+ "PREFIX vitro-public: \n" +
+ "PREFIX p.29: \n" +
+ "PREFIX vivo: \n" +
+ "\n" +
+ "#\n" +
+ "# This example query gets 20 geographic locations\n" +
+ "# and (if available) their labels\n" +
+ "#\n" +
+ "SELECT ?geoLocation ?label\n" +
+ "WHERE\n" +
+ "{\n" +
+ " ?geoLocation rdf:type vivo:GeographicLocation\n" +
+ " OPTIONAL { ?geoLocation rdfs:label ?label } \n" +
+ "}\n" +
+ "LIMIT 20";
+
+
+ }
+}