You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/02/22 16:21:36 UTC

[29/37] MARMOTTA-105: refactoring of packages in remaining platform modules

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java
new file mode 100644
index 0000000..c65cb9e
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/LinkVersionSerializer.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.io;
+
+import org.apache.marmotta.platform.versioning.utils.MementoUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.commons.http.ContentType;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.Resource;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Serializes an ordered list of versions in application/link-format into an output stream
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+@ApplicationScoped
+public class LinkVersionSerializer implements VersionSerializer {
+
+    @Inject
+    ConfigurationService configurationService;
+
+    //a static list thta contains the contentTypes
+    private static final List<ContentType> contentTypes = new ArrayList(){{
+        add(new ContentType("application","link-format"));
+    }};
+
+    /**
+     * return the content type that will be produced
+     * @return
+     */
+    public ContentType getContentType() {
+        return new ContentType("application","link-format");
+    }
+
+    /**
+     * returns a list of supported content types (application/link-format)
+     * @return a list of types
+     */
+    @Override
+    public List<ContentType> getContentTypes() {
+        return contentTypes;
+    }
+
+    /**
+     * writes serialized version list (application/link-format) to output stream
+     * @param original the original (current) resource
+     * @param versions a list of versions in ascending order
+     * @param out an output stream
+     */
+    @Override
+    public void write(Resource original, RepositoryResult<Version> versions, OutputStream out) throws IOException {
+
+        try {
+            BufferedWriter w = new BufferedWriter(new OutputStreamWriter(out));
+
+            //write original resource
+            w.append("<");
+            w.append(original.toString());
+            w.append(">;rel=\"original\",");
+            w.newLine();
+
+            //to control the loop
+            boolean first = true;
+
+            //write versions
+            while (versions.hasNext()) {
+
+                Version v = versions.next();
+
+                //append memento resource uri for versions v
+                w.append("<");
+                w.append(MementoUtils.resourceURI(original.toString(),v.getCommitTime(),configurationService.getBaseUri()).toString());
+                w.append(">; rel=\"");
+
+                //write first, last, memento
+                if( first && versions.hasNext()) {
+                    w.append("first memento");
+                } else if(!versions.hasNext()) {
+                    w.append("last memento");
+                } else {
+                    w.append("memento");
+                }
+
+                //add datetime
+                w.append("\"; datetime=\"");
+                w.append(v.getCommitTime().toString());
+                w.append("\",");
+
+                w.newLine();
+                first = false;
+            }
+
+            w.flush();
+            w.close();
+
+        } catch (RepositoryException e) {
+            throw new IOException("cannot serialize versions in application/link-format");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/VersionSerializer.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/VersionSerializer.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/VersionSerializer.java
new file mode 100644
index 0000000..8eb4799
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/io/VersionSerializer.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.io;
+
+import org.apache.marmotta.commons.http.ContentType;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.Resource;
+import org.openrdf.repository.RepositoryResult;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * Serializes an ordered list of versions into an output stream
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+public interface VersionSerializer {
+
+    /**
+     * returns a list of supported content types
+     * @return
+     */
+    public List<ContentType> getContentTypes();
+
+    /**
+     * return the content type that will be produced
+     * @return
+     */
+    public ContentType getContentType();
+
+    /**
+     * writes serialized version list to output stream
+     * @param original the original (current) resource
+     * @param versions a list of versions in ascending order
+     * @param out an output stream
+     */
+    public void write(Resource original, RepositoryResult<Version> versions, OutputStream out) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java
new file mode 100644
index 0000000..2a57cad
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/model/MementoVersionSet.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.model;
+
+import org.apache.marmotta.platform.versioning.utils.MementoUtils;
+import org.apache.marmotta.platform.versioning.exception.MementoException;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.Resource;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This POJO represents a set of resource versions including last, first, prev, next and current versions
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+public class MementoVersionSet {
+
+    private Version first;
+    private Version last;
+    private Version previous;
+    private Version next;
+    private Version current;
+    private Resource original;
+
+    public MementoVersionSet(Resource resource) {
+        this.original = resource;
+    }
+
+    public Set<String> buildLinks(String baseURI) throws MementoException {
+
+        String prefix =  baseURI +
+                MementoUtils.MEMENTO_WEBSERVICE + "/" +
+                MementoUtils.MEMENTO_RESOURCE + "/";
+
+        HashSet<String> links = new HashSet<String>();
+
+        //first, last and current are mandatory
+        if( first == null || last == null || current == null) throw new MementoException("Memento links cannot be produced");
+
+        links.add(buildLink(prefix,original.toString(),first.getCommitTime(),"first memento"));
+        links.add(buildLink(prefix,original.toString(),last.getCommitTime(),"last memento"));
+        links.add(buildLink(prefix,original.toString(),current.getCommitTime(),"memento"));
+
+        //add link to original
+        links.add("<"+original.toString()+">;rel=\"original\"");
+
+        //add next and previous if they exist
+        if( next != null ) links.add(buildLink(prefix,original.toString(),next.getCommitTime(),"next memento"));
+        if( previous != null ) links.add(buildLink(prefix,original.toString(),previous.getCommitTime(),"prev memento"));
+
+        return links;
+    }
+
+    private String buildLink( String prefix, String resource, Date date, String rel ) {
+        return  "<" + prefix + MementoUtils.MEMENTO_DATE_FORMAT.format(date) + "/" + resource +
+                ">;datetime=\"" + date.toString() + "\";rel=\"" + rel +"\"";
+    }
+
+    public Resource getOriginal() {
+        return original;
+    }
+
+    public Version getFirst() {
+        return first;
+    }
+
+    public void setFirst(Version first) {
+        this.first = first;
+    }
+
+    public Version getLast() {
+        return last;
+    }
+
+    public void setLast(Version last) {
+        this.last = last;
+    }
+
+    public Version getPrevious() {
+        return previous;
+    }
+
+    public void setPrevious(Version previous) {
+        this.previous = previous;
+    }
+
+    public Version getNext() {
+        return next;
+    }
+
+    public void setNext(Version next) {
+        this.next = next;
+    }
+
+    public Version getCurrent() {
+        return current;
+    }
+
+    public void setCurrent(Version current) {
+        this.current = current;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/MementoServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/MementoServiceImpl.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/MementoServiceImpl.java
new file mode 100644
index 0000000..1e28b28
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/MementoServiceImpl.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.services;
+
+import org.apache.marmotta.platform.versioning.api.MementoService;
+import org.apache.marmotta.platform.versioning.exception.MementoException;
+import org.apache.marmotta.platform.versioning.model.MementoVersionSet;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.Resource;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.sail.SailException;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import java.util.Date;
+
+/**
+ * ...
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+@ApplicationScoped
+public class MementoServiceImpl implements MementoService {
+
+    @Inject
+    VersioningSailProvider versioningService;
+
+    /**
+     * returns the version for a resource that was current on the given date
+     * @param resource a uri resource
+     * @param date a date
+     * @return the version with respect to the date
+     * @throws MementoException
+     */
+    @Override
+    public Version getVersion(Resource resource, Date date) throws MementoException {
+        try {
+            return versioningService.getLatestVersion(resource,date);
+        } catch (SailException e) {
+            throw new MementoException("version for "+date+" cannot be returned");
+        }
+    }
+
+    /**
+     * returns a memento version set that includes first, last, current, prev and next version with respect
+     * to a given date and resource
+     * @param resource a requested resource
+     * @param date a requested date
+     * @return a memento version set
+     * @throws MementoException
+     * @see MementoVersionSet
+     */
+    @Override
+    public MementoVersionSet getVersionSet(Resource resource, Date date) throws MementoException {
+        try {
+            MementoVersionSet versionset = new MementoVersionSet(resource);
+
+            //get current version
+            versionset.setCurrent(versioningService.getLatestVersion(resource,date));
+
+            //loop to all versions to fill the versionset
+            RepositoryResult<Version> versions = versioningService.listVersions(resource);
+
+            while(versions.hasNext()) {
+
+                Version v = versions.next();
+
+                //set first as current if there is no current version yet
+                if(versionset.getCurrent() == null) versionset.setCurrent(v);
+
+                //set first version
+                if(versionset.getFirst() == null) versionset.setFirst(v);
+
+                //set last version
+                versionset.setLast(v);
+
+                //set previous as long as id is smaller than the current one
+                if(v.getId() < versionset.getCurrent().getId()) {
+                    versionset.setPrevious(v);
+                }
+
+                //set next if it is not set yet and the id is greater than the current one
+                if(v.getId() > versionset.getCurrent().getId() && versionset.getNext() == null) {
+                    versionset.setNext(v);
+                }
+            }
+
+            return versionset;
+        } catch (SailException e) {
+            throw new MementoException("cannot list versions");
+        } catch (RepositoryException e) {
+            throw new MementoException("cannot produce version result set");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java
new file mode 100644
index 0000000..79cb339
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersionSerializerServiceImpl.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.services;
+
+import org.apache.marmotta.platform.versioning.api.VersionSerializerService;
+import org.apache.marmotta.platform.versioning.io.VersionSerializer;
+import org.apache.marmotta.commons.http.ContentType;
+import org.apache.marmotta.commons.http.LMFHttpUtils;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Returns a adequate serializer for a given list of ContentTypes
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+@ApplicationScoped
+public class VersionSerializerServiceImpl implements VersionSerializerService {
+
+    @Inject @Any
+    Instance<VersionSerializer> serializers;
+
+    /**
+     * returns an adequate serializer for a mimetype
+     * @param type a list of mimetype (from Accept header)
+     * @return a serializer
+     * @throws IOException if there is no serializer for mimetype
+     */
+    @Override
+    public VersionSerializer getSerializer(List<ContentType> type) throws IOException {
+        for(VersionSerializer serializer : serializers) {
+            if(LMFHttpUtils.bestContentType(serializer.getContentTypes(),type) != null) return serializer;
+        }
+        throw new IOException("Cannot find serializer for " + type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
new file mode 100644
index 0000000..5b04339
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/services/VersioningSailProvider.java
@@ -0,0 +1,225 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.services;
+
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.marmotta.platform.core.api.triplestore.TransactionalSailProvider;
+import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
+
+import org.apache.marmotta.commons.sesame.filter.AllOfFilter;
+import org.apache.marmotta.commons.sesame.filter.SesameFilter;
+import org.apache.marmotta.commons.sesame.filter.statement.StatementFilter;
+import org.apache.marmotta.kiwi.transactions.api.TransactionalSail;
+import org.apache.marmotta.kiwi.transactions.wrapper.TransactionalSailWrapper;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.apache.marmotta.kiwi.versioning.repository.SnapshotRepositoryConnection;
+import org.apache.marmotta.kiwi.versioning.sail.KiWiVersioningSail;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.sail.SailException;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A SAIL provider wrapping a versioning component around the repository
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+@ApplicationScoped
+public class VersioningSailProvider implements TransactionalSailProvider {
+
+    public static final String VERSIONING_ENABLED = "versioning.enabled";
+    @Inject
+    private Logger                    log;
+
+    @Inject
+    private ConfigurationService configurationService;
+
+    @Inject
+    private SesameService sesameService;
+
+    @Inject
+    @Named("versioning")
+    private Instance<StatementFilter> filters;
+
+
+    private KiWiVersioningSail sail;
+
+    /**
+     * Return the name of the provider. Used e.g. for displaying status information or logging.
+     *
+     * @return
+     */
+    @Override
+    public String getName() {
+        return "Versioning";
+    }
+
+    /**
+     * Return true if this sail provider is enabled in the configuration.
+     *
+     * @return
+     */
+    @Override
+    public boolean isEnabled() {
+        return configurationService.getBooleanConfiguration(VERSIONING_ENABLED,true);
+    }
+
+
+    public void configurationChanged(@Observes ConfigurationChangedEvent e) {
+        if(e.containsChangedKey(VERSIONING_ENABLED)) {
+            sesameService.shutdown();
+            sesameService.initialise();
+        }
+    }
+
+    /**
+     * Create the sail wrapper provided by this SailProvider
+     *
+     * @param parent the parent sail to wrap by the provider
+     * @return the wrapped sail
+     */
+    @Override
+    public TransactionalSailWrapper createSail(TransactionalSail parent) {
+        Set<SesameFilter<Statement>> sFilters = new HashSet<SesameFilter<Statement>>();
+
+        StatementFilter filterCached = new StatementFilter() {
+            @Override
+            public boolean accept(Statement object) {
+                if(object.getContext() != null && configurationService.getCacheContext().equals(object.getContext().stringValue())) return false;
+                else
+                    return true;
+            }
+        };
+        sFilters.add(filterCached);
+
+        StatementFilter filterInferred = new StatementFilter() {
+            @Override
+            public boolean accept(Statement object) {
+                if(object.getContext() != null && configurationService.getInferredContext().equals(object.getContext().stringValue())) return false;
+                else
+                    return true;
+            }
+        };
+        sFilters.add(filterInferred);
+
+        StatementFilter filterEnhancing = new StatementFilter() {
+            @Override
+            public boolean accept(Statement object) {
+                if(object.getContext() != null && configurationService.getEnhancerContex().equals(object.getContext().stringValue())) return false;
+                else
+                    return true;
+            }
+        };
+        sFilters.add(filterEnhancing);
+
+        Iterator<StatementFilter> fIt = filters.iterator();
+        while (fIt.hasNext()) {
+            StatementFilter f = fIt.next();
+            log.info("Auto-Registering filter {}", f.getClass().getSimpleName());
+            sFilters.add(f);
+        }
+
+        sail = new KiWiVersioningSail(parent, new AllOfFilter<Statement>(sFilters));
+
+        return sail;
+    }
+
+    /**
+     * Get a read-only snapshot of the repository at the given date. Returns a sail connection that
+     * can be used to access the triple data. Any attempts to modify the underlying data will throw
+     * a SailReadOnlyException.
+     *
+     * @param snapshotDate the date of which to take the snapshot; the snapshot will consist of all
+     *                     triples that have been created before or at the date and deleted after that date
+     *                     (or not deleted at all).
+     * @return a read-only sail connection to access the data of the triple store at the given date
+     */
+    public SnapshotRepositoryConnection getSnapshot(Date snapshotDate) throws RepositoryException {
+        try {
+            return new SnapshotRepositoryConnection(sesameService.getRepository(),sail.getSnapshot(snapshotDate));
+        } catch (SailException e) {
+            throw new RepositoryException(e);
+        }
+    }
+
+    /**
+     * List all versions of this repository.
+     *
+     * @return
+     */
+    public RepositoryResult<Version> listVersions() throws SailException {
+        return sail.listVersions();
+    }
+
+    /**
+     * List all versions of this repository between a start and end date.
+     *
+     * @return
+     */
+    public RepositoryResult<Version> listVersions(Date from, Date to) throws SailException {
+        return sail.listVersions(from, to);
+    }
+
+    /**
+     * List all versions of this repository affecting the given resource as subject.
+     *
+     * @return
+     */
+    public RepositoryResult<Version> listVersions(Resource r) throws SailException {
+        return sail.listVersions(r);
+    }
+
+    /**
+     * List all versions of this repository affecting the given resource as subject between a start and end date.
+     *
+     * @return
+     */
+    public RepositoryResult<Version> listVersions(Resource r, Date from, Date to) throws SailException {
+        return sail.listVersions(r, from, to);
+    }
+
+    public Version getVersion(Long id) throws SailException {
+        return sail.getVersion(id);
+    }
+
+    /**
+     * Return the version that is the most recent version for a resource given a reference date. The method will either
+     * return the version that was current for the resource at the given date or return null in case such a version
+     * does not exist (e.g. before the resource was created).
+     *
+     * @param resource  the resource for which to find a version
+     * @param date      the reference date
+     * @return the latest version of the resource at the given date, or null if such a version does not exist
+     * @throws java.sql.SQLException
+     */
+    public Version getLatestVersion(Resource r, Date date) throws SailException {
+        return sail.getLatestVersion(r, date);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java
new file mode 100644
index 0000000..ac09c9b
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/utils/MementoUtils.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.utils;
+
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * ...
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+public class MementoUtils {
+
+    public static final String MEMENTO_WEBSERVICE = "memento";
+    public static final String MEMENTO_TIMEGATE = "timegate";
+    public static final String MEMENTO_TIMEMAP = "timemap";
+    public static final String MEMENTO_RESOURCE = "resource";
+
+    /**
+     * is used for date format used in memento resource uris
+     */
+    public static final DateFormat MEMENTO_DATE_FORMAT = 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
+     * @param resource  the resource that should be represented by the permalink
+     * @return a permalink
+     */
+    public static URI resourceURI(String resource, Date date, String baseURI) {
+        return URI.create(
+                baseURI +
+                        MEMENTO_WEBSERVICE + "/" +
+                        MEMENTO_RESOURCE + "/" +
+                        MEMENTO_DATE_FORMAT.format(date) + "/" +
+                        resource);
+    }
+
+    /**
+     * builds a memento timemap uri
+     * @param resource  the resource that should be represented
+     * @return a timemap uri
+     */
+    public static URI timemapURI(String resource, String baseURI) {
+        return URI.create(
+                baseURI +
+                        MEMENTO_WEBSERVICE + "/" +
+                        MEMENTO_TIMEMAP + "/" +
+                        resource);
+    }
+
+    /**
+     * builds a memento timemap uri
+     * @param resource  the resource that should be represented
+     * @return a timemap uri
+     */
+    public static URI timegateURI(String resource, String baseURI) {
+        return URI.create(
+                baseURI +
+                        MEMENTO_WEBSERVICE + "/" +
+                        MEMENTO_TIMEGATE + "/" +
+                        resource);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java
new file mode 100644
index 0000000..7ec37da
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/MementoWebService.java
@@ -0,0 +1,323 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.webservices;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+
+import org.apache.marmotta.platform.versioning.api.VersionSerializerService;
+import org.apache.marmotta.platform.versioning.io.VersionSerializer;
+import org.apache.marmotta.platform.versioning.utils.MementoUtils;
+import org.apache.marmotta.platform.versioning.api.MementoService;
+import org.apache.marmotta.platform.versioning.exception.MementoException;
+import org.apache.marmotta.platform.versioning.model.MementoVersionSet;
+import org.apache.marmotta.platform.versioning.services.VersioningSailProvider;
+import com.google.common.base.Preconditions;
+import org.apache.marmotta.commons.sesame.repository.ResourceUtils;
+import org.apache.marmotta.commons.util.DateUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.io.LMFIOService;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.marmotta.commons.collections.CollectionUtils;
+import org.apache.marmotta.commons.http.ContentType;
+import org.apache.marmotta.commons.http.LMFHttpUtils;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.URI;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.Rio;
+import org.openrdf.sail.SailException;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Webservice manages memento related services, namely:
+ * <ul>
+ *     <li>Memento TimeGate Service: points to permalinks representing resource versions</li>
+ *     <li>Memento Resource Service: delivers versions of resources based on a permalink</li>
+ *     <li>Memento TimeBundle Service: TODO implement</li>
+ *     <li>Memento TimeMap Service: TODO implement</li>
+ * </ul>
+ * <p/>
+ * Author: Thomas Kurz (tkurz@apache.org)
+ */
+@ApplicationScoped
+@Path("/" + MementoUtils.MEMENTO_WEBSERVICE)
+public class MementoWebService {
+
+    @Inject
+    private Logger log;
+    @Inject
+    private ConfigurationService configurationService;
+    @Inject
+    private SesameService sesameService;
+    @Inject
+    private MementoService mementoService;
+    @Inject
+    private VersioningSailProvider versioningService;
+    @Inject
+    private LMFIOService lmfIOService;
+    @Inject
+    private VersionSerializerService versionSerializerService;
+
+    /**
+     * redirects to memento permalink resource
+     * @param date_string the requested datetime
+     * @param resource_string the requested resource string
+     * @return a HTTP response
+     * @HTTP 303 found resource on given location
+     * @HTTP 400 some errors in request
+     * @HTTP 404 resource or version cannot be found
+     * @HTTP 500 any other failure
+     */
+    @GET
+    @Path("/" + MementoUtils.MEMENTO_TIMEGATE + "/{resource:.+}")
+    public Response timgateService(@PathParam("resource") String resource_string, @HeaderParam("Accept-Datetime") String date_string) {
+
+        try {
+            //check preconditions
+            Preconditions.checkNotNull(resource_string,"Resource URI may not null");
+            Preconditions.checkNotNull(date_string, "Accept-Datetime Header may not be null");
+
+            RepositoryConnection conn = sesameService.getConnection();
+
+            try {
+                Date date = DateUtils.parseDate(date_string);
+
+                URI resource = ResourceUtils.getUriResource(conn, resource_string);
+
+                //get versions
+                MementoVersionSet versions = mementoService.getVersionSet(resource, date);
+
+                //build version links
+                Set<String> links = versions.buildLinks(configurationService.getBaseUri());
+
+                //add timemap link
+                links.add("<" + MementoUtils.timemapURI(resource_string, configurationService.getBaseUri()) + ">;rel=timemap");
+
+                //return permalink
+                return Response
+                        .status(301)
+                        .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", CollectionUtils.fold(links, ", "))
+                        .build();
+
+            } catch (MementoException e) {
+                return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
+            }  finally {
+                conn.commit();
+                conn.close();
+            }
+        } catch (RepositoryException e) {
+            return Response.serverError().entity("Versioning sail cannot be initialized").build();
+        } catch (IllegalArgumentException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        } catch (NullPointerException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }
+    }
+
+    /**
+     * returns a serialisation for a given memento resource uri
+     * @param date_string the date of the version
+     * @param resource_string the original resource uri
+     * @param types_string the accepted content types
+     * @return a HTTP response
+     * @HTTP 200 return resource in requested format
+     * @HTTP 400 some errors in request
+     * @HTTP 404 resource or version cannot be found
+     * @HTTP 500 any other failure
+     */
+    @GET
+    @Path("/" + MementoUtils.MEMENTO_RESOURCE + "/{date:[^/]+}/{resource:.+}")
+    public Response resourceService(@PathParam("date")String date_string,
+                                    @PathParam("resource") String resource_string,
+                                    @HeaderParam("Accept") String types_string) {
+
+        try {
+            //check preconditions
+            Preconditions.checkNotNull(resource_string,"Resource URI may not null");
+            Preconditions.checkNotNull(date_string, "Date may not be null");
+            Preconditions.checkNotNull(types_string, "Accept Header may not be null");
+
+            RepositoryConnection conn = sesameService.getConnection();
+
+            try {
+                final Date date = MementoUtils.MEMENTO_DATE_FORMAT.parse(date_string);
+
+                final URI resource = ResourceUtils.getUriResource(conn, resource_string);
+
+                final ContentType type = getContentType(types_string);
+
+                //get serializer
+                final RDFFormat serializer = lmfIOService.getSerializer(type.getMime());
+
+                //create response serialisation
+                StreamingOutput entity = new StreamingOutput() {
+                    @Override
+                    public void write(OutputStream output) throws IOException, WebApplicationException {
+                        RDFWriter writer = Rio.createWriter(serializer, output);
+                        try {
+                            RepositoryConnection con = versioningService.getSnapshot(date);
+                            URI subject = con.getValueFactory().createURI(resource.stringValue());
+                            try {
+                                con.exportStatements(subject,null,null,true,writer);
+                            } catch (RepositoryException e) {
+                                throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+                            } catch (RDFHandlerException e) {
+                                throw new IOException("error while writing RDF data to stream");
+                            } finally {
+                                con.commit();
+                                con.close();
+                            }
+                        } catch (RepositoryException e) {
+                            throw new WebApplicationException(e, Response.Status.INTERNAL_SERVER_ERROR);
+                        }
+                    }
+                };
+
+                //get versions
+                MementoVersionSet versions = mementoService.getVersionSet(resource, date);
+
+                //build version links
+                Set<String> links = versions.buildLinks(configurationService.getBaseUri());
+
+                //add timegate link
+                links.add("<" + MementoUtils.timegateURI(resource_string, configurationService.getBaseUri()) + ">;rel=timegate");
+
+                //add timemap link
+                links.add("<" + MementoUtils.timemapURI(resource_string, configurationService.getBaseUri()) + ">;rel=timemap");
+
+                //create response
+                return Response
+                        .ok()
+                        .header("Link", CollectionUtils.fold(links," ,"))
+                        .header("Content-Type", type.toString())
+                        .header("Memento-Datetime", versions.getCurrent().getCommitTime().toString())
+                        .entity(entity)
+                        .build();
+
+            } catch (ParseException e) {
+                return Response.status(Response.Status.BAD_REQUEST).entity("Cannot parse date").build();
+            } catch (IllegalArgumentException e) {
+                return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+            } catch (MementoException e) {
+                return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
+            } finally {
+                conn.commit();
+                conn.close();
+            }
+        } catch (IllegalArgumentException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }  catch (RepositoryException e) {
+            return Response.serverError().entity("Versioning sail cannot be initialized").build();
+        } catch (NullPointerException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }
+    }
+
+    @GET
+    @Path("/" + MementoUtils.MEMENTO_TIMEMAP + "/{resource:.+}")
+    public Response timemapService(@PathParam("resource") String resource_string,
+                                   @HeaderParam("Accept") String types_string) {
+
+        try {
+            //check preconditions
+            Preconditions.checkNotNull(resource_string,"Resource URI may not null");
+            Preconditions.checkNotNull(types_string, "Accept Header may not be null");
+
+            RepositoryConnection conn = sesameService.getConnection();
+
+            try {
+
+                final URI resource = ResourceUtils.getUriResource(conn, resource_string);
+
+                List<ContentType> types = LMFHttpUtils.parseAcceptHeader(types_string);
+
+                //get versions
+                final RepositoryResult<Version> versions = versioningService.listVersions(resource);
+
+                //get serializer
+                final VersionSerializer serializer = versionSerializerService.getSerializer(types);
+
+                //create response serialisation
+                StreamingOutput entity = new StreamingOutput() {
+                    @Override
+                    public void write(OutputStream output) throws IOException, WebApplicationException {
+                        serializer.write(resource,versions,output);
+                    }
+                };
+
+                //create Header Links
+                Set<String> links = new HashSet<String>();
+                links.add("<" + MementoUtils.timegateURI(resource_string, configurationService.getBaseUri()) + ">;rel=timegate");
+
+                links.add("<" + resource_string + ">;rel=original");
+
+                //create response
+                return Response
+                        .ok()
+                        .header("Link", CollectionUtils.fold(links," ,"))
+                        .header("Content-Type", serializer.getContentType().toString())
+                        .entity(entity)
+                        .build();
+
+            } catch (SailException e) {
+                return Response.status(Response.Status.NOT_FOUND).entity("Cannot list versions").build();
+            } catch (IOException e) {
+                return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).entity("cannot produce content type").build();
+            } finally {
+                conn.commit();
+                conn.close();
+            }
+        } catch (RepositoryException e) {
+            return Response.serverError().entity("Versioning sail cannot be initialized").build();
+        } catch (NullPointerException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        }
+    }
+
+    /**
+     * returns the best fitting content type for accept type header string
+     * @param types a string of types
+     * @return a content type that is supported by the running system
+     * @throws IllegalArgumentException if no type is supported
+     */
+    private ContentType getContentType(String types) throws IllegalArgumentException {
+        List<ContentType> acceptedTypes = LMFHttpUtils.parseAcceptHeader(types);
+        List<ContentType> offeredTypes  = LMFHttpUtils.parseStringList(lmfIOService.getProducedTypes());
+        ContentType type = LMFHttpUtils.bestContentType(offeredTypes,acceptedTypes);
+        if(type == null) throw new IllegalArgumentException("Requested type is not supported");
+        return type;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
new file mode 100644
index 0000000..5ad7a01
--- /dev/null
+++ b/platform/marmotta-versioning/src/main/java/org/apache/marmotta/platform/versioning/webservices/VersioningWebService.java
@@ -0,0 +1,203 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed 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.marmotta.platform.versioning.webservices;
+
+import org.apache.marmotta.platform.versioning.services.VersioningSailProvider;
+import org.apache.marmotta.commons.sesame.repository.ResourceUtils;
+import org.apache.marmotta.commons.util.DateUtils;
+import org.apache.marmotta.commons.util.JSONUtils;
+
+import info.aduna.iteration.Iterations;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.api.triplestore.SesameService;
+import org.apache.marmotta.platform.core.events.SystemStartupEvent;
+import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.openrdf.model.URI;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.sail.SailException;
+import org.slf4j.Logger;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Webservice allowing access to the versioning functionality of the LMF. Provides the following functionalities:
+ * <ul>
+ *     <li>list all versions that are affecting a resource</li>
+ *     <li>return detailed information for a version</li>
+ * </ul>
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@ApplicationScoped
+@Path("/")
+public class VersioningWebService {
+
+    @Inject
+    private Logger log;
+
+    @Inject
+    private VersioningSailProvider versioningService;
+
+    @Inject
+    private SesameService sesameService;
+
+
+    @Inject
+    private ConfigurationService configurationService;
+
+    public void startup(@Observes SystemStartupEvent event) {
+        if(configurationService.getBooleanConfiguration("versioning.memento",true)) {
+            log.info("Versioning Service: enabling Memento support");
+            configurationService.setRuntimeFlag("create_memento_links",true);
+        }
+    }
+
+
+    /**
+     * Return a list of versions that affect the resource whose uri is passed as argument. For each version,
+     * the result will contain the id, the creator, and the date when the version was recorded. Further details
+     * for a version can be requested by calling the /versioning/versions/{id} webservice.
+     * <p/>
+     * Note that resource_uri is an optional parameter. In case no resource uri is given, all versions recorded
+     * by the LMF are returned, which can take a considerable amount of time.
+     *
+     * @HTTP 200 in case the versions were retrieved successfully
+     * @HTTP 404 in case the resource passed as argument resource_uri could not be found
+     *
+     * @param resource_uri the URI of the resource for which to return the versions (optional, see warning above)
+     * @return a JSON list of versions, each a map with the properties "id" (long), "creator" (uri), "date" (ISO 8601 String)
+     */
+    @GET
+    @Produces("application/json")
+    @Path("/versions/list")
+    public Response getVersions(@QueryParam("resource") String resource_uri,
+                                @QueryParam("from") String dateFrom, @QueryParam("to") String dateTo) {
+        try {
+            RepositoryConnection conn = sesameService.getConnection();
+            try {
+                if(resource_uri != null) {
+                    URI resource = ResourceUtils.getUriResource(conn,resource_uri);
+                    if(resource != null && resource instanceof KiWiUriResource) {
+
+                        if(dateFrom == null && dateTo == null) {
+                            return Response.ok().entity(formatVersions(versioningService.listVersions(resource))).build();
+                        } else {
+                            Date dateFromD = DateUtils.parseDate(dateFrom);
+                            Date dateToD   = DateUtils.parseDate(dateTo);
+                            return Response.ok().entity(formatVersions(versioningService.listVersions(resource,dateFromD,dateToD))).build();
+                        }
+                    } else {
+                        return Response.status(Response.Status.NOT_FOUND).entity("resource with URI "+resource_uri+" was not found in the system").build();
+                    }
+                } else {
+                    if(dateFrom == null && dateTo == null) {
+                        return Response.ok().entity(formatVersions(versioningService.listVersions())).build();
+                    } else {
+                        Date dateFromD = DateUtils.parseDate(dateFrom);
+                        Date dateToD   = DateUtils.parseDate(dateTo);
+                        return Response.ok().entity(formatVersions(versioningService.listVersions(dateFromD,dateToD))).build();
+                    }
+                }
+            } finally {
+                conn.commit();
+                conn.close();
+            }
+        } catch(RepositoryException ex) {
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
+        } catch(SailException ex) {
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
+        }
+
+    }
+
+    private List<Map<String,Object>> formatVersions(RepositoryResult<Version> versions) throws RepositoryException {
+        return formatVersions(Iterations.asList(versions));
+    }
+
+    private List<Map<String,Object>> formatVersions(List<Version> versions) {
+        List<Map<String,Object>> result = new ArrayList<Map<String, Object>>(versions.size());
+
+        for(Version version : versions) {
+            Map<String,Object> v_map = new HashMap<String, Object>();
+            v_map.put("id",version.getId());
+            if(version.getCreator() != null) {
+                v_map.put("creator",version.getCreator().stringValue());
+            }
+            v_map.put("date", DateUtils.ISO8601FORMAT.format(version.getCommitTime()));
+
+            result.add(v_map);
+        }
+
+        return result;
+    }
+
+
+    /**
+     * Return detailed information about the version whose id is passed as path argument. Returns a JSON map
+     * with the fields id, creator, date, added_triples, removed_triples. Triple will be represented in RDF/JSON format.
+     *
+     * @HTTP 404 in case the requested version does not exist
+     *
+     * @param id the ID of the version to return
+     * @return a JSON map representing the version information as described above
+     */
+    @GET
+    @Produces("application/json")
+    @Path("/versions/{id:[0-9]+}")
+    public Response getVersion(@PathParam("id") Long id) {
+        try {
+            Version version = versioningService.getVersion(id);
+
+            if(version != null) {
+                Map<String,Object> result = new HashMap<String, Object>();
+                result.put("id",version.getId());
+                if(version.getCreator() != null) {
+                    result.put("creator", version.getCreator().stringValue());
+                }
+                result.put("date",    DateUtils.ISO8601FORMAT.format(version.getCommitTime()));
+
+                result.put("added_triples", JSONUtils.serializeTriplesAsJson(version.getAddedTriples()));
+                result.put("removed_triples", JSONUtils.serializeTriplesAsJson(version.getRemovedTriples()));
+
+                return Response.ok().entity(result).build();
+
+            } else {
+                return Response.status(Response.Status.NOT_FOUND).entity("version with id "+id+" does not exist").build();
+            }
+
+        } catch (SailException e) {
+            return Response.serverError().entity("error loading version "+id+": "+e.getMessage()).build();
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/69cbd57a/platform/marmotta-versioning/src/main/resources/kiwi-module.properties
----------------------------------------------------------------------
diff --git a/platform/marmotta-versioning/src/main/resources/kiwi-module.properties b/platform/marmotta-versioning/src/main/resources/kiwi-module.properties
index 18fa794..b739052 100644
--- a/platform/marmotta-versioning/src/main/resources/kiwi-module.properties
+++ b/platform/marmotta-versioning/src/main/resources/kiwi-module.properties
@@ -20,8 +20,8 @@ weight=70
 
 baseurl=/versioning
 
-webservices=at.newmedialab.lmf.versioning.webservices.VersioningWebService,\
-  at.newmedialab.lmf.versioning.webservices.MementoWebService
+webservices=org.apache.marmotta.platform.versioning.webservices.VersioningWebService,\
+  org.apache.marmotta.platform.versioning.webservices.MementoWebService
 
 icon_small = /admin/img/clock_small.png