From cd789c9b1a26d886550269b170536874c0125dfa Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Thu, 13 Oct 2016 15:49:15 +0200 Subject: [PATCH 1/6] redirect of timegate ist set to 302 response code --- .../platform/versioning/webservices/MementoWebService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java index 5faccf9fc..e4818017f 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java @@ -125,7 +125,7 @@ public Response timgateService(@PathParam("resource") String resource_string, @H //return permalink return Response - .status(301) + .status(302) .location(MementoUtils.resourceURI(resource_string, versions.getCurrent().getCommitTime(), configurationService.getBaseUri())) .header(VARY, "negotiate, accept-datetime, accept") .header("Memento-Datetime", versions.getCurrent().getCommitTime().toString()) From d216030b01ad921b36e2aeb96aec1468590ffe51 Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Thu, 13 Oct 2016 17:48:21 +0200 Subject: [PATCH 2/6] TimeGate now responds with the most recent Memento if date is not given. Tests are added. --- platform/marmotta-versioning-kiwi/pom.xml | 55 +++++++++++++++ .../webservices/MementoWebService.java | 11 ++- .../versioning/MementoWebServiceTest.java | 69 +++++++++++++++++++ .../src/test/resources/data_v1.ttl | 2 + .../src/test/resources/data_v2.ttl | 1 + 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java create mode 100644 platform/marmotta-versioning-kiwi/src/test/resources/data_v1.ttl create mode 100644 platform/marmotta-versioning-kiwi/src/test/resources/data_v2.ttl diff --git a/platform/marmotta-versioning-kiwi/pom.xml b/platform/marmotta-versioning-kiwi/pom.xml index f49926d65..53ba8b079 100644 --- a/platform/marmotta-versioning-kiwi/pom.xml +++ b/platform/marmotta-versioning-kiwi/pom.xml @@ -170,6 +170,61 @@ org.apache.marmotta kiwi-versioning + + + org.apache.marmotta + marmotta-core + ${project.version} + test-jar + test + + + org.eclipse.jetty + jetty-server + ${jetty.version} + test + + + org.eclipse.jetty + jetty-servlet + ${jetty.version} + test + + + junit + junit + test + + + org.jboss.weld.se + weld-se-core + test + + + javax.el + javax.el-api + test + + + com.h2database + h2 + test + + + com.jayway.restassured + rest-assured + test + + + org.hamcrest + hamcrest-library + test + + + org.hamcrest + hamcrest-core + test + diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java index e4818017f..2f7dec4d3 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java @@ -106,11 +106,18 @@ public Response timgateService(@PathParam("resource") String resource_string, @H try { //check preconditions Preconditions.checkNotNull(resource_string,"Resource URI may not null"); - Preconditions.checkNotNull(date_string, "Accept-Datetime Header may not be null"); final RepositoryConnection conn = sesameService.getConnection(); try { - Date date = DateUtils.parseDate(date_string); + + //if date_string is not set, get NOW, else parse date_string + Date date = null; + + if(date_string == null) { + date = new Date(); + } else { + DateUtils.parseDate(date_string); + } URI resource = conn.getValueFactory().createURI(resource_string); diff --git a/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java new file mode 100644 index 000000000..1b165ffac --- /dev/null +++ b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java @@ -0,0 +1,69 @@ +package org.apache.marmotta.platform.versioning; + +import com.jayway.restassured.RestAssured; +import org.apache.marmotta.platform.core.api.importer.ImportService; +import org.apache.marmotta.platform.core.api.triplestore.ContextService; +import org.apache.marmotta.platform.core.api.user.UserService; +import org.apache.marmotta.platform.core.exception.io.MarmottaImportException; +import org.apache.marmotta.platform.core.test.base.JettyMarmotta; +import org.apache.marmotta.platform.versioning.utils.MementoUtils; +import org.apache.marmotta.platform.versioning.webservices.MementoWebService; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.net.URISyntaxException; + +import static com.jayway.restassured.RestAssured.expect; + +/** + * @author Thomas Kurz (tkurz@apache.org) + * @since 13.10.16. + */ +public class MementoWebServiceTest { + + private static Logger log = LoggerFactory.getLogger(MementoWebServiceTest.class); + + private static JettyMarmotta marmotta; + + @BeforeClass + public static void setUp() throws MarmottaImportException, URISyntaxException { + marmotta = new JettyMarmotta("/marmotta", MementoWebService.class); + + ImportService importService = marmotta.getService(ImportService.class); + UserService userService = marmotta.getService(UserService.class); + ContextService contextService = marmotta.getService(ContextService.class); + + //import some data + InputStream is_v1 = Thread.currentThread().getContextClassLoader().getResourceAsStream("data_v1.ttl"); + int n_v1 = importService.importData(is_v1, "text/turtle", userService.getAnonymousUser(), contextService.getDefaultContext()); + log.info("Imported RDF data_v1 with {} triples", n_v1); + + //import some data including updates + InputStream is_v2 = Thread.currentThread().getContextClassLoader().getResourceAsStream("data_v2.ttl"); + int n_v2 = importService.importData(is_v2, "text/turtle", userService.getAnonymousUser(), contextService.getDefaultContext()); + log.info("Imported RDF data_v2 with {} triples", n_v2); + + RestAssured.baseURI = "http://localhost"; + RestAssured.port = marmotta.getPort(); + RestAssured.basePath = marmotta.getContext(); + } + + @AfterClass + public static void tearDown() { + marmotta.shutdown(); + } + + @Test + public void testNegotiationResponse() { + expect(). + log().ifError(). + statusCode(302). + when().request().redirects().follow(false). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEGATE + "/http://example.org/resource1"); + } + +} diff --git a/platform/marmotta-versioning-kiwi/src/test/resources/data_v1.ttl b/platform/marmotta-versioning-kiwi/src/test/resources/data_v1.ttl new file mode 100644 index 000000000..1cae34858 --- /dev/null +++ b/platform/marmotta-versioning-kiwi/src/test/resources/data_v1.ttl @@ -0,0 +1,2 @@ + "v1". + "v1". \ No newline at end of file diff --git a/platform/marmotta-versioning-kiwi/src/test/resources/data_v2.ttl b/platform/marmotta-versioning-kiwi/src/test/resources/data_v2.ttl new file mode 100644 index 000000000..c80a86da8 --- /dev/null +++ b/platform/marmotta-versioning-kiwi/src/test/resources/data_v2.ttl @@ -0,0 +1 @@ + "v2". \ No newline at end of file From badefd3e66ef85feab6837ca5f9f6c415c398e91 Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Thu, 13 Oct 2016 17:51:56 +0200 Subject: [PATCH 3/6] TimeGate does not provice a Memento-Datetime anaymore. --- .../versioning/webservices/MementoWebService.java | 1 - .../platform/versioning/MementoWebServiceTest.java | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java index 2f7dec4d3..9d35e59d1 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java @@ -135,7 +135,6 @@ public Response timgateService(@PathParam("resource") String resource_string, @H .status(302) .location(MementoUtils.resourceURI(resource_string, versions.getCurrent().getCommitTime(), configurationService.getBaseUri())) .header(VARY, "negotiate, accept-datetime, accept") - .header("Memento-Datetime", versions.getCurrent().getCommitTime().toString()) .header(LINK, Joiner.on(", ").join(links)) .build(); diff --git a/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java index 1b165ffac..c78b55152 100644 --- a/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java +++ b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java @@ -16,6 +16,7 @@ import java.io.InputStream; import java.net.URISyntaxException; +import java.util.Date; import static com.jayway.restassured.RestAssured.expect; @@ -29,6 +30,8 @@ public class MementoWebServiceTest { private static JettyMarmotta marmotta; + private static Date date1,date2,date3; + @BeforeClass public static void setUp() throws MarmottaImportException, URISyntaxException { marmotta = new JettyMarmotta("/marmotta", MementoWebService.class); @@ -37,16 +40,22 @@ public static void setUp() throws MarmottaImportException, URISyntaxException { UserService userService = marmotta.getService(UserService.class); ContextService contextService = marmotta.getService(ContextService.class); + date1 = new Date(); + //import some data InputStream is_v1 = Thread.currentThread().getContextClassLoader().getResourceAsStream("data_v1.ttl"); int n_v1 = importService.importData(is_v1, "text/turtle", userService.getAnonymousUser(), contextService.getDefaultContext()); log.info("Imported RDF data_v1 with {} triples", n_v1); + date2 = new Date(); + //import some data including updates InputStream is_v2 = Thread.currentThread().getContextClassLoader().getResourceAsStream("data_v2.ttl"); int n_v2 = importService.importData(is_v2, "text/turtle", userService.getAnonymousUser(), contextService.getDefaultContext()); log.info("Imported RDF data_v2 with {} triples", n_v2); + date3 = new Date(); + RestAssured.baseURI = "http://localhost"; RestAssured.port = marmotta.getPort(); RestAssured.basePath = marmotta.getContext(); From ea07757c176138c5a59b3cace0c1249e48711e68 Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Thu, 13 Oct 2016 18:09:52 +0200 Subject: [PATCH 4/6] Use different date serializations for uris and other places (e.g. links, headers, etc.) --- .../platform/versioning/model/MementoVersionSet.java | 2 +- .../marmotta/platform/versioning/utils/MementoUtils.java | 5 ++++- .../platform/versioning/webservices/MementoWebService.java | 2 +- .../src/main/resources/templates/memento_timemap.ftl | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java index 594cab879..c1a71c278 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java @@ -70,7 +70,7 @@ public Set buildLinks(String baseURI) throws MementoException { } private String buildLink( String prefix, String resource, Date date, String rel ) { - return "<" + prefix + MementoUtils.MEMENTO_DATE_FORMAT.format(date) + "/" + resource + + return "<" + prefix + MementoUtils.MEMENTO_DATE_FORMAT_FOR_URIS.format(date) + "/" + resource + ">;datetime=\"" + MementoUtils.MEMENTO_DATE_FORMAT.format(date) + "\";rel=\"" + rel +"\""; } diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java index 5fa2f7137..5742952e5 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java @@ -36,9 +36,12 @@ public class MementoUtils { /** * is used for date format used in memento resource uris + * TODO should be HTTP Date format specified by RFC 1123 and in the GMT timezone like "Mon, 19 Sep 2016 23:47:12 GMT" */ public static final DateFormat MEMENTO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); + public static final DateFormat MEMENTO_DATE_FORMAT_FOR_URIS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); + /** * builds a memento permalink * @param date the date of the version that should be represented by the permalink @@ -50,7 +53,7 @@ public static URI resourceURI(String resource, Date date, String baseURI) { baseURI + MEMENTO_WEBSERVICE + "/" + MEMENTO_RESOURCE + "/" + - MEMENTO_DATE_FORMAT.format(date) + "/" + + MEMENTO_DATE_FORMAT_FOR_URIS.format(date) + "/" + resource); } diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java index 9d35e59d1..9174715ba 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java @@ -179,7 +179,7 @@ public Response resourceService(@PathParam("date")String date_string, RepositoryConnection conn = sesameService.getConnection(); try { - final Date date = MementoUtils.MEMENTO_DATE_FORMAT.parse(date_string); + final Date date = MementoUtils.MEMENTO_DATE_FORMAT_FOR_URIS.parse(date_string); final URI resource = conn.getValueFactory().createURI(resource_string); diff --git a/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl b/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl index 92f474548..4deff7973 100644 --- a/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl +++ b/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl @@ -56,7 +56,7 @@ var target = "#timeknots", v = [ <#list versions as version> - {'name':"${version.date}", 'date':new Date("${version.tstamp}"), 'uri':"${version.uri}"}, + {'name':"${MEMENTO_DATE_FORMAT.format(version.date)}", 'date':new Date("${version.tstamp}"), 'uri':"${version.uri}"}, {'name':"now", 'date':new Date(),'lineWidth':1, 'uri':"${SERVER_URL}resource?uri=${original?url}"} ]; @@ -88,7 +88,7 @@ <#list versions as version> - ${version.date} + ${MEMENTO_DATE_FORMAT.format(version.date)} From 837d5d0e4097e3ebb69ee40f593873e499a6cce2 Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Thu, 13 Oct 2016 18:11:46 +0200 Subject: [PATCH 5/6] set link to most recent browser extension --- .../src/main/resources/web/admin/about.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/marmotta-versioning-kiwi/src/main/resources/web/admin/about.html b/platform/marmotta-versioning-kiwi/src/main/resources/web/admin/about.html index f72bd528c..17964ca13 100644 --- a/platform/marmotta-versioning-kiwi/src/main/resources/web/admin/about.html +++ b/platform/marmotta-versioning-kiwi/src/main/resources/web/admin/about.html @@ -87,7 +87,7 @@

Memento SupportMementoFox browser + archives, e.g. the Memento For Chrome browser extension.

From 385a92bc7f4f4a11dcdf63864c9cf04b6a6e08cc Mon Sep 17 00:00:00 2001 From: Thomas Kurz Date: Wed, 19 Oct 2016 16:04:26 +0200 Subject: [PATCH 6/6] some fixes and tests --- .../versioning/io/HtmlVersionSerializer.java | 3 +- .../versioning/io/LinkVersionSerializer.java | 4 +- .../versioning/model/MementoVersionSet.java | 9 +- .../VersionSerializerServiceImpl.java | 16 ++- .../versioning/utils/MementoUtils.java | 26 ++++- .../webservices/MementoWebService.java | 4 +- .../resources/templates/memento_timemap.ftl | 4 +- .../versioning/MementoWebServiceTest.java | 105 +++++++++++++++++- 8 files changed, 155 insertions(+), 16 deletions(-) diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/HtmlVersionSerializer.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/HtmlVersionSerializer.java index edbf006f9..881ca02c2 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/HtmlVersionSerializer.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/HtmlVersionSerializer.java @@ -94,7 +94,7 @@ public void write(Resource original, RepositoryResult versions, OutputS //write data to map Map data = new HashMap(); - data.put("original",original.toString()); + data.put("original", MementoUtils.originalURI(original.toString(),configurationService.getBaseUri())); List> vs = new ArrayList>(); @@ -102,6 +102,7 @@ public void write(Resource original, RepositoryResult versions, OutputS Version v = versions.next(); Map m = new HashMap(); m.put("date",v.getCommitTime().toString()); + m.put("formatedDate", MementoUtils.MEMENTO_DATE_FORMAT.format(v.getCommitTime())); m.put("uri",MementoUtils.resourceURI(original.toString(), v.getCommitTime(), configurationService.getBaseUri()).toString()); m.put("tstamp", TSTAMP.format(v.getCommitTime())); vs.add(m); diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java index 60f2aaef7..5bac7dd5e 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java @@ -80,7 +80,7 @@ public void write(Resource original, RepositoryResult versions, OutputS //write original resource w.append("<"); - w.append(original.toString()); + w.append(MementoUtils.originalURI(original.toString(), configurationService.getBaseUri()).toString()); w.append(">;rel=\"original\","); w.newLine(); @@ -108,7 +108,7 @@ public void write(Resource original, RepositoryResult versions, OutputS //add datetime w.append("\"; datetime=\""); - w.append(v.getCommitTime().toString()); + w.append(MementoUtils.MEMENTO_DATE_FORMAT.format(v.getCommitTime())); w.append("\","); w.newLine(); diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java index c1a71c278..a3ce5be18 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java @@ -18,10 +18,13 @@ package org.apache.marmotta.platform.versioning.model; import org.apache.marmotta.kiwi.versioning.model.Version; +import org.apache.marmotta.platform.core.api.config.ConfigurationService; import org.apache.marmotta.platform.versioning.exception.MementoException; import org.apache.marmotta.platform.versioning.utils.MementoUtils; import org.openrdf.model.Resource; +import javax.inject.Inject; +import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashSet; import java.util.Set; @@ -60,7 +63,11 @@ public Set buildLinks(String baseURI) throws MementoException { links.add(buildLink(prefix,original.toString(),current.getCommitTime(),"memento")); //add link to original - links.add("<"+original.toString()+">;rel=\"original\""); + try { + links.add("<"+MementoUtils.originalURI(original.toString(),baseURI).toString()+">;rel=\"original\""); + } catch (UnsupportedEncodingException e) { + throw new MementoException(e); + } //add next and previous if they exist if( next != null ) links.add(buildLink(prefix,original.toString(),next.getCommitTime(),"next memento")); diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java index 579e167b1..b4b535c6e 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java @@ -42,15 +42,19 @@ public class VersionSerializerServiceImpl implements VersionSerializerService { /** * returns an adequate serializer for a mimetype - * @param type a list of mimetype (from Accept header) + * @param types a list of mimetype (from Accept header) * @return a serializer * @throws IOException if there is no serializer for mimetype */ @Override - public VersionSerializer getSerializer(List type) throws IOException { - for(VersionSerializer serializer : serializers) { - if(MarmottaHttpUtils.bestContentType(serializer.getContentTypes(),type) != null) return serializer; - } - throw new IOException("Cannot find serializer for " + type); + public VersionSerializer getSerializer(List types) throws IOException { + for(ContentType type : types) { + for(VersionSerializer serializer : serializers) { + for(ContentType stype : serializer.getContentTypes()) { + if(stype.matches(type)) return serializer; + } + } + } //TODO there is not fuzzy match e.g. text/* + throw new IOException("Cannot find serializer for " + types); } } diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java index 5742952e5..6df05a011 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java @@ -17,10 +17,16 @@ */ package org.apache.marmotta.platform.versioning.utils; +import org.apache.marmotta.platform.core.api.config.ConfigurationService; + +import java.io.UnsupportedEncodingException; import java.net.URI; +import java.net.URLEncoder; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; /** * ... @@ -38,10 +44,28 @@ public class MementoUtils { * is used for date format used in memento resource uris * TODO should be HTTP Date format specified by RFC 1123 and in the GMT timezone like "Mon, 19 Sep 2016 23:47:12 GMT" */ - public static final DateFormat MEMENTO_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); + public static final DateFormat MEMENTO_DATE_FORMAT; + + static { + MEMENTO_DATE_FORMAT = new SimpleDateFormat( + "EEE, dd MMM yyyy HH:mm:ss z", Locale.US); //TODO which locale should be used? + MEMENTO_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); + } public static final DateFormat MEMENTO_DATE_FORMAT_FOR_URIS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); + public static URI originalURI(String resource, String baseURI) throws UnsupportedEncodingException { + + if(resource.startsWith(baseURI)) { + return URI.create(resource); + } else { + return URI.create( + baseURI + + ConfigurationService.RESOURCE_PATH + "?uri=" + + URLEncoder.encode(resource, "UTF-8")); + } + } + /** * builds a memento permalink * @param date the date of the version that should be represented by the permalink diff --git a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java index 9174715ba..ae9b653ba 100644 --- a/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java +++ b/platform/marmotta-versioning-kiwi/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java @@ -116,7 +116,7 @@ public Response timgateService(@PathParam("resource") String resource_string, @H if(date_string == null) { date = new Date(); } else { - DateUtils.parseDate(date_string); + date = DateUtils.parseDate(date_string); } URI resource = conn.getValueFactory().createURI(resource_string); @@ -288,7 +288,7 @@ public void write(OutputStream output) throws IOException, WebApplicationExcepti Set links = new HashSet(); links.add("<" + MementoUtils.timegateURI(resource_string, configurationService.getBaseUri()) + ">;rel=timegate"); - links.add("<" + resource_string + ">;rel=original"); + links.add("<" + MementoUtils.originalURI(resource_string, configurationService.getBaseUri()) + ">;rel=original"); //create response return Response diff --git a/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl b/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl index 4deff7973..16843e514 100644 --- a/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl +++ b/platform/marmotta-versioning-kiwi/src/main/resources/templates/memento_timemap.ftl @@ -56,7 +56,7 @@ var target = "#timeknots", v = [ <#list versions as version> - {'name':"${MEMENTO_DATE_FORMAT.format(version.date)}", 'date':new Date("${version.tstamp}"), 'uri':"${version.uri}"}, + {'name':"${version.formatedDate}", 'date':new Date("${version.tstamp}"), 'uri':"${version.uri}"}, {'name':"now", 'date':new Date(),'lineWidth':1, 'uri':"${SERVER_URL}resource?uri=${original?url}"} ]; @@ -88,7 +88,7 @@ <#list versions as version> - ${MEMENTO_DATE_FORMAT.format(version.date)} + ${version.formatedDate} diff --git a/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java index c78b55152..7aa647e86 100644 --- a/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java +++ b/platform/marmotta-versioning-kiwi/src/test/java/org/apache/marmotta/platform/versioning/MementoWebServiceTest.java @@ -1,6 +1,8 @@ package org.apache.marmotta.platform.versioning; import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.response.ValidatableResponse; import org.apache.marmotta.platform.core.api.importer.ImportService; import org.apache.marmotta.platform.core.api.triplestore.ContextService; import org.apache.marmotta.platform.core.api.user.UserService; @@ -8,6 +10,9 @@ import org.apache.marmotta.platform.core.test.base.JettyMarmotta; import org.apache.marmotta.platform.versioning.utils.MementoUtils; import org.apache.marmotta.platform.versioning.webservices.MementoWebService; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.core.IsEqual; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -16,9 +21,14 @@ import java.io.InputStream; import java.net.URISyntaxException; +import java.text.ParseException; import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import static com.jayway.restassured.RestAssured.expect; +import static com.jayway.restassured.RestAssured.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertTrue; /** * @author Thomas Kurz (tkurz@apache.org) @@ -75,4 +85,97 @@ public void testNegotiationResponse() { get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEGATE + "/http://example.org/resource1"); } + @Test + public void testTimemapWithoutMementoDatetimeHeader() { + expect(). + log().ifError().header("Memento-Datetime", isEmptyOrNullString()). + when().request().redirects().follow(false). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEGATE + "/http://example.org/resource1"); + } + + @Test + public void testWithDatetimeHeader() { + expect(). + log().ifError(). + when().request().redirects().follow(false). + header("Accept-Datetime","Mon, 19 Sep 2016 23:47:12 GMT"). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEGATE + "/http://example.org/resource1"); + } + + @Test + public void testDateFormatForTimemap() { + when(). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEMAP + "/http://example.org/resource1"). + then().body(containsValidMementoDatetimeFormats("datetime=\"([^\"]+)\"")); + } + + @Test + public void testDateFormatForLinkHeaders() { + //timemap + expect(). + log().ifError(). + when().request().redirects().follow(false). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEMAP + "/http://example.org/resource1"). + then().header("date",containsValidMementoDatetimeFormats("(.+)")); + + //timegate + String location = given().request().redirects().follow(false). + when(). + get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEGATE + "/http://example.org/resource1"). + then(). + header("date",containsValidMementoDatetimeFormats("(.+)")). + header("link", containsValidMementoDatetimeFormats("datetime=\"([^\"]+)\"")).extract().header("location"); + + //memento resource + when(). + get(location). + then(). + header("date", containsValidMementoDatetimeFormats("(.+)")). + header("memento-datetime",containsValidMementoDatetimeFormats("(.+)")). + header("link", containsValidMementoDatetimeFormats("datetime=\"([^\"]+)\"")).extract().header("location"); + } + + @Test + public void testTimemapSerialization() { + expect() + .log().ifError() + .when() + .request().header("Accept", "text / html, application / xhtml + xml, application/xml;q=0.9,image/webp,*/*;q=0.8") + .get(MementoUtils.MEMENTO_WEBSERVICE + "/" + MementoUtils.MEMENTO_TIMEMAP + "/http://example.org/resource1") + .then() + .contentType(is("text / html")); + } + + //matcher tests if all matching groups are in correct memento datetime serialization + private org.hamcrest.Matcher containsValidMementoDatetimeFormats(final String pattern) { + return new BaseMatcher() { + + private String lastGroup; + + @Override + public boolean matches(final Object item) { + + Pattern p = Pattern.compile(pattern); + + Matcher m = p.matcher((String)item); + + while(m.find()) { + lastGroup = m.group(1); + try { + Date date = MementoUtils.MEMENTO_DATE_FORMAT.parse(lastGroup); + if(!lastGroup.equals(MementoUtils.MEMENTO_DATE_FORMAT.format(date))) return false; + } catch (ParseException ex) { + return false; + } + } + + return true; + } + @Override + public void describeTo(final Description description) { + description.appendText("datetime does not match MementoDatetime: ").appendText(lastGroup); + } + }; + } + }