You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2014/03/03 14:25:35 UTC

[2/2] git commit: MARMOTTA-449: implemented LDP-NR accroding the last spec (sec. 6.2.3.12)

MARMOTTA-449: implemented LDP-NR accroding the last spec (sec. 6.2.3.12)


Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/3c1962b6
Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/3c1962b6
Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/3c1962b6

Branch: refs/heads/ldp
Commit: 3c1962b6cfe05b6162751b9a8cb90ec6969ceef2
Parents: 20d8794
Author: Sergio Fernández <wi...@apache.org>
Authored: Mon Mar 3 14:23:52 2014 +0100
Committer: Sergio Fernández <wi...@apache.org>
Committed: Mon Mar 3 14:23:52 2014 +0100

----------------------------------------------------------------------
 .../marmotta/platform/ldp/api/LdpService.java   | 35 +++++++-
 .../platform/ldp/services/LdpServiceImpl.java   | 48 +++++++---
 .../marmotta/platform/ldp/util/LdpUtils.java    | 95 ++++++++++++++++++++
 .../platform/ldp/util/LdpWebServiceUtils.java   | 74 ---------------
 .../platform/ldp/webservices/LdpWebService.java | 39 ++++----
 5 files changed, 183 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/marmotta/blob/3c1962b6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
index 7978273..8f49e82 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
@@ -40,6 +40,7 @@ import java.util.List;
  *  LDP Service
  *
  *  @author Sergio Fernández
+ *  @author Jakob Frank
  */
 public interface LdpService {
 
@@ -47,9 +48,37 @@ public interface LdpService {
 
     boolean exists(RepositoryConnection connection, URI resource) throws RepositoryException;
 
-    boolean addResource(RepositoryConnection connection, String container, String resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException;
-
-    boolean addResource(RepositoryConnection connection, URI container, URI resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException;
+    boolean exists(RepositoryConnection connection, URI resource, URI type) throws RepositoryException;
+
+    /**
+     * Add a LDP resource
+     *
+     * @param connection repository connection
+     * @param container container where add the resource
+     * @param resource resource to add
+     * @param type mimetype of the posted resource
+     * @param stream stream from where read the resource representation
+     * @return resource location
+     * @throws RepositoryException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    String addResource(RepositoryConnection connection, String container, String resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException;
+
+    /**
+     * Add a LDP resource
+     *
+     * @param connection repository connection
+     * @param container container where add the resource
+     * @param resource resource to add
+     * @param type mimetype of the posted resource
+     * @param stream stream from where read the resource representation
+     * @return resource location
+     * @throws RepositoryException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    String addResource(RepositoryConnection connection, URI container, URI resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException;
 
     List<Statement> getLdpTypes(RepositoryConnection connection, String resource) throws RepositoryException;
 

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3c1962b6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
index 2cd4fc3..e5eea4e 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
@@ -32,7 +32,7 @@ import org.apache.marmotta.platform.ldp.patch.RdfPatchUtil;
 import org.apache.marmotta.platform.ldp.patch.model.PatchLine;
 import org.apache.marmotta.platform.ldp.patch.parser.ParseException;
 import org.apache.marmotta.platform.ldp.patch.parser.RdfPatchParserImpl;
-import org.apache.marmotta.platform.ldp.util.LdpWebServiceUtils;
+import org.apache.marmotta.platform.ldp.util.LdpUtils;
 import org.openrdf.model.*;
 import org.openrdf.model.impl.ValueFactoryImpl;
 import org.openrdf.model.vocabulary.RDF;
@@ -91,6 +91,11 @@ public class LdpServiceImpl implements LdpService {
     }
 
     @Override
+    public boolean exists(RepositoryConnection connection, URI resource, URI type) throws RepositoryException {
+        return connection.hasStatement(resource, RDF.TYPE, type, true, ldpContext);
+    }
+
+    @Override
     public List<Statement> getLdpTypes(RepositoryConnection connection, String resource) throws RepositoryException {
         return getLdpTypes(connection, buildURI(resource));
     }
@@ -121,7 +126,7 @@ public class LdpServiceImpl implements LdpService {
                 connection.getStatements(resource, null, null, false, ldpContext)
         );
         try {
-            LdpWebServiceUtils.exportIteration(writer, resource, union);
+            LdpUtils.exportIteration(writer, resource, union);
         } finally {
             union.close();
         }
@@ -145,12 +150,12 @@ public class LdpServiceImpl implements LdpService {
     }
 
     @Override
-    public boolean addResource(RepositoryConnection connection, String container, String resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException {
+    public String addResource(RepositoryConnection connection, String container, String resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException {
         return addResource(connection, buildURI(container), buildURI(resource), type, stream);
     }
 
     @Override
-    public boolean addResource(RepositoryConnection connection, URI container, URI resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException {
+    public String addResource(RepositoryConnection connection, URI container, URI resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException {
         ValueFactory valueFactory = connection.getValueFactory();
 
         // Add container triples (Sec. 6.4.3)
@@ -158,31 +163,48 @@ public class LdpServiceImpl implements LdpService {
 
         Literal now = valueFactory.createLiteral(new Date());
 
-        connection.add(container, RDF.TYPE, LDP.BasicContainer, ldpContext);
+        if (exists(connection, container, LDP.BasicContainer)) {
+            connection.remove(container, DCTERMS.modified, null, ldpContext);
+        } else {
+            connection.add(container, RDF.TYPE, LDP.BasicContainer, ldpContext);
+        }
+
         connection.add(container, LDP.contains, resource, ldpContext);
-        connection.remove(container, DCTERMS.modified, null, ldpContext);
         connection.add(container, DCTERMS.modified, now, ldpContext);
 
-        connection.add(resource, RDF.TYPE, LDP.Resource, ldpContext);
-        connection.add(resource, DCTERMS.created, now, ldpContext);
-        connection.add(resource, DCTERMS.modified, now, ldpContext);
-
         // Add the bodyContent
         log.trace("Content ({}) for new resource <{}>", type, resource);
         final RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(type.toString());
         if (rdfFormat == null) {
             log.debug("POST creates new LDP-BR, because no RDF parser found for type {}", type);
             Literal format = valueFactory.createLiteral(type.toString());
-            connection.add(resource, DCTERMS.format, format, ldpContext); //nie:mimeType ?
+            URI binaryResource = valueFactory.createURI(resource.stringValue() + LdpUtils.getExtension(type.toString()));
+
+            //connection.add(resource, RDF.TYPE, LDP.NonRdfResource, ldpContext); //TODO:
+            connection.add(binaryResource, DCTERMS.created, now, ldpContext);
+            connection.add(binaryResource, DCTERMS.modified, now, ldpContext);
+
+            //extra triples
+            //TODO: check conformance with 6.2.3.12
+            connection.add(binaryResource, DCTERMS.format, format, ldpContext); //nie:mimeType ?
+            connection.add(binaryResource, DCTERMS.isFormatOf, resource, ldpContext);
+
             //TODO: something else?
-            return binaryStore.store(resource, stream); //TODO: control exceptions
+
+            binaryStore.store(binaryResource, stream);//TODO: exceptions control
+
+            return binaryResource.stringValue();
         } else {
             log.debug("POST creates new LDP-RR, data provided as {}", rdfFormat.getName());
 
+            connection.add(resource, RDF.TYPE, LDP.Resource, ldpContext);
+            connection.add(resource, DCTERMS.created, now, ldpContext);
+            connection.add(resource, DCTERMS.modified, now, ldpContext);
+
             // FIXME: We are (are we?) allowed to filter out server-managed properties here
             connection.add(stream, resource.stringValue(), rdfFormat, resource);
 
-            return true;
+            return resource.stringValue();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3c1962b6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpUtils.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpUtils.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpUtils.java
new file mode 100644
index 0000000..dc565b4
--- /dev/null
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpUtils.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.platform.ldp.util;
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.marmotta.commons.vocabulary.LDP;
+import org.apache.marmotta.commons.vocabulary.XSD;
+import org.apache.tika.mime.MimeType;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.vocabulary.DCTERMS;
+import org.openrdf.model.vocabulary.RDF;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFWriter;
+
+/**
+ * Various Util-Methods for the {@link org.apache.marmotta.platform.ldp.api.LdpService}.
+ */
+public class LdpUtils {
+
+    /**
+     * Urify the Slug: header value, i.e. replace all non-url chars with a single dash.
+     *
+     * @param slugHeaderValue the client-provided Slug-header
+     * @return the slugHeaderValue "urified"
+     */
+    public static String urify(String slugHeaderValue) {
+        return slugHeaderValue.trim()
+                // Replace non-url chars with '-'
+                .replaceAll("[^\\w]+", "-");
+    }
+
+    /**
+     * Get the preferred file extension for the content type
+     *
+     * @param contentType content type
+     * @return file extension (already including '.')
+     * @throws MimeTypeException
+     */
+    public static String getExtension(String contentType) {
+        MimeTypes allTypes = MimeTypes.getDefaultMimeTypes();
+        try {
+            MimeType mimeType = allTypes.forName(contentType);
+            return mimeType.getExtension();
+        } catch (MimeTypeException e) {
+            return null; //FIXME
+        }
+
+    }
+
+    /**
+     * LDP-Style to serialize a resource.
+     *
+     * @param writer the writer to serialize to
+     * @param subject the resource to serialize
+     * @param iteration the Iteration containing the data
+     * @throws RDFHandlerException
+     * @throws RepositoryException
+     */
+    public static void exportIteration(RDFWriter writer, URI subject, CloseableIteration<Statement, RepositoryException> iteration) throws RDFHandlerException, RepositoryException {
+        writer.startRDF();
+
+        writer.handleNamespace(LDP.PREFIX, LDP.NAMESPACE);
+        writer.handleNamespace(RDF.PREFIX, RDF.NAMESPACE);
+        writer.handleNamespace(XSD.PREFIX, XSD.NAMESPACE);
+        writer.handleNamespace(DCTERMS.PREFIX, DCTERMS.NAMESPACE);
+
+        writer.handleNamespace("", subject.stringValue());
+
+        while (iteration.hasNext()) {
+            writer.handleStatement(iteration.next());
+        }
+
+        writer.endRDF();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3c1962b6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
deleted file mode 100644
index 1116879..0000000
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/util/LdpWebServiceUtils.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.marmotta.platform.ldp.util;
-
-import info.aduna.iteration.CloseableIteration;
-import info.aduna.iteration.Iteration;
-import info.aduna.iteration.UnionIteration;
-import org.apache.marmotta.commons.vocabulary.LDP;
-import org.apache.marmotta.commons.vocabulary.XSD;
-import org.openrdf.model.Statement;
-import org.openrdf.model.URI;
-import org.openrdf.model.vocabulary.DCTERMS;
-import org.openrdf.model.vocabulary.RDF;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.rio.RDFHandlerException;
-import org.openrdf.rio.RDFWriter;
-
-/**
- * Various Util-Methods for the {@link org.apache.marmotta.platform.ldp.webservices.LdpWebService}.
- */
-public class LdpWebServiceUtils {
-
-    /**
-     * Urify the Slug: header value, i.e. replace all non-url chars with a single dash.
-     *
-     * @param slugHeaderValue the client-provided Slug-header
-     * @return the slugHeaderValue "urified"
-     */
-    public static String urify(String slugHeaderValue) {
-        return slugHeaderValue
-                // Replace non-url chars with '-'
-                .replaceAll("[^\\w]+", "-");
-    }
-
-    /**
-     * LDP-Style to serialize a resource.
-     * @param writer the writer to serialize to
-     * @param subject the resource to serialize
-     * @param iteration the Iteration containing the data
-     * @throws RDFHandlerException
-     * @throws RepositoryException
-     */
-    public static void exportIteration(RDFWriter writer, URI subject, CloseableIteration<Statement, RepositoryException> iteration) throws RDFHandlerException, RepositoryException {
-        writer.startRDF();
-
-        writer.handleNamespace(LDP.PREFIX, LDP.NAMESPACE);
-        writer.handleNamespace(RDF.PREFIX, RDF.NAMESPACE);
-        writer.handleNamespace(XSD.PREFIX, XSD.NAMESPACE);
-        writer.handleNamespace(DCTERMS.PREFIX, DCTERMS.NAMESPACE);
-
-        writer.handleNamespace("", subject.stringValue());
-
-        while (iteration.hasNext()) {
-            writer.handleStatement(iteration.next());
-        }
-
-        writer.endRDF();
-    }
-}

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3c1962b6/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
index 88da2e3..f10da48 100644
--- a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
+++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
@@ -27,7 +27,7 @@ import org.apache.marmotta.platform.ldp.patch.InvalidPatchDocumentException;
 import org.apache.marmotta.platform.ldp.patch.parser.ParseException;
 import org.apache.marmotta.platform.ldp.patch.parser.RdfPatchParser;
 import org.apache.marmotta.platform.ldp.util.EntityTagUtils;
-import org.apache.marmotta.platform.ldp.util.LdpWebServiceUtils;
+import org.apache.marmotta.platform.ldp.util.LdpUtils;
 import org.jboss.resteasy.spi.NoLogWebApplicationException;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
@@ -178,11 +178,8 @@ public class LdpWebService {
         final String container = getResourceUri(uriInfo);
         log.debug("POST to LDPC <{}>", container);
 
-        final RepositoryConnection con = sesameService.getConnection();
+        final RepositoryConnection conn = sesameService.getConnection();
         try {
-            con.begin();
-            // TODO: Check if resource (container) exists
-            log.warn("NOT CHECKING EXISTENCE OF <{}>", container);
 
             final String localName;
             if (StringUtils.isBlank(slug)) {
@@ -193,21 +190,23 @@ public class LdpWebService {
                 // Honor client wishes from Slug-header (Sec. 6.4.11)
                 //    http://www.ietf.org/rfc/rfc5023.txt
                 log.trace("Slug-Header is '{}'", slug);
-                localName = LdpWebServiceUtils.urify(slug);
+                localName = LdpUtils.urify(slug);
                 log.trace("Slug-Header urified: {}", localName);
             }
 
             String newResource = uriInfo.getRequestUriBuilder().path(localName).build().toString();
 
+            conn.begin();
+
             log.trace("Checking possible name clash for new resource <{}>", newResource);
-            if (ldpService.exists(con, newResource)) {
+            if (ldpService.exists(conn, newResource)) {
                 int i = 0;
                 final String base = newResource;
                 do {
                     final String candidate = base + "-" + (++i);
                     log.trace("<{}> already exists, trying <{}>", newResource, candidate);
                     newResource = candidate;
-                } while (ldpService.exists(con, newResource));
+                } while (ldpService.exists(conn, newResource));
                 log.debug("resolved name clash, new resource will be <{}>", newResource);
             } else {
                 log.debug("no name clash for <{}>", newResource);
@@ -215,25 +214,29 @@ public class LdpWebService {
 
             log.debug("POST to <{}> will create new LDP-R <{}>", container, newResource);
 
+            //checking if resource (container) exists is done later in the service
             try {
-                ldpService.addResource(con, container, newResource, type, postBody);
-                final Response.ResponseBuilder resp = createResponse(con, Response.Status.CREATED, container).location(java.net.URI.create(newResource));
-                con.commit();
-                return resp.build();
+                String location = ldpService.addResource(conn, container, newResource, type, postBody);
+                final Response.ResponseBuilder response = createResponse(conn, Response.Status.CREATED, container).location(java.net.URI.create(location));
+                if (newResource.compareTo(location) != 0) {
+                    response.link(newResource, "describedby"); //Sec. 6.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15
+                }
+                conn.commit();
+                return response.build();
             } catch (IOException | RDFParseException e) {
-                final Response.ResponseBuilder resp = createResponse(con, Response.Status.BAD_REQUEST, container).entity(e.getClass().getSimpleName() + ": " + e.getMessage());
-                con.rollback();
+                final Response.ResponseBuilder resp = createResponse(conn, Response.Status.BAD_REQUEST, container).entity(e.getClass().getSimpleName() + ": " + e.getMessage());
+                conn.rollback();
                 return resp.build();
             } catch (UnsupportedRDFormatException e) {
-                final Response.ResponseBuilder resp = createResponse(con, Response.Status.UNSUPPORTED_MEDIA_TYPE, container).entity(e);
-                con.rollback();
+                final Response.ResponseBuilder resp = createResponse(conn, Response.Status.UNSUPPORTED_MEDIA_TYPE, container).entity(e);
+                conn.rollback();
                 return resp.build();
             }
         } catch (final Throwable t) {
-            con.rollback();
+            conn.rollback();
             throw t;
         } finally {
-            con.close();
+            conn.close();
         }
     }