MARMOTTA-449: draft implementation for storing LDP-BRs (i.e., non LDP-RR)
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/f59d008e Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/f59d008e Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/f59d008e Branch: refs/heads/develop Commit: f59d008e1abd408de900658a08b100c046f05cb5 Parents: 7b2de20 Author: Sergio Fernández <[email protected]> Authored: Sun Mar 2 12:29:50 2014 +0100 Committer: Sergio Fernández <[email protected]> Committed: Sun Mar 2 12:29:50 2014 +0100 ---------------------------------------------------------------------- .../platform/ldp/api/LdpBinaryStoreService.java | 40 +++++++ .../ldp/services/LdpBinaryStoreServiceImpl.java | 108 +++++++++++++++++++ .../platform/ldp/services/LdpServiceImpl.java | 40 ++++--- 3 files changed, 167 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/f59d008e/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java new file mode 100644 index 0000000..8e5d67d --- /dev/null +++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java @@ -0,0 +1,40 @@ +/* + * 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.api; + +import org.openrdf.model.URI; + +import java.io.InputStream; +import java.net.URISyntaxException; + +/** + * LDP Store Service + * + * @author Sergio Fernández + */ +public interface LdpBinaryStoreService { + + boolean store(String resource, InputStream stream); + + boolean store(URI resource, InputStream stream); + + InputStream read(String resource); + + InputStream read(URI resource); + +} http://git-wip-us.apache.org/repos/asf/marmotta/blob/f59d008e/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java new file mode 100644 index 0000000..7476336 --- /dev/null +++ b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java @@ -0,0 +1,108 @@ +/* + * 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.services; + +import org.apache.commons.lang.StringUtils; +import org.apache.marmotta.platform.core.api.config.ConfigurationService; +import org.apache.marmotta.platform.core.events.SystemStartupEvent; +import org.apache.marmotta.platform.ldp.api.LdpBinaryStoreService; +import org.openrdf.model.URI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.inject.Inject; +import java.io.*; +import java.net.URISyntaxException; + +/** + * Very basic disk-based implementation of the LDP Binary Store + * + * @author Sergio Fernández + */ +@ApplicationScoped +public class LdpBinaryStoreServiceImpl implements LdpBinaryStoreService { + + private static final Logger log = LoggerFactory.getLogger(LdpBinaryStoreServiceImpl.class); + + @Inject + private ConfigurationService configurationService; + + private File base; + + public void init(@Observes SystemStartupEvent e) { + base = new File(configurationService.getHome(), "data"); + if (!base.exists()) { + base.mkdir(); + } + log.info("Initialized binary data store over {}", base.getAbsolutePath()); + } + + private File getFile(String resource) throws URISyntaxException { + java.net.URI uri = new java.net.URI(resource); + String schema = uri.getScheme(); + if ("http".compareTo(schema) != 0) { + String msg = "Binary storage not supported for URIs with " + schema + " as schema"; + log.error(msg); + throw new RuntimeException(msg); + } + return new File(base, StringUtils.removeStart(resource, "http://")); + } + + @Override + public boolean store(String resource, InputStream stream) { + try { + File file = getFile(resource); + File dir = file.getParentFile(); + if (!dir.exists()) { + dir.mkdirs(); + } + + OutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); + int token = -1; + while((token = stream.read()) != -1) { + bufferedOutputStream.write(token); + } + bufferedOutputStream.flush(); + bufferedOutputStream.close(); + stream.close(); + + return true; + } catch (URISyntaxException | IOException e) { + log.error("{} resource cannot be stored on disk: {}", resource, e.getMessage()); + return false; + } + } + + @Override + public boolean store(URI resource, InputStream stream) { + return store(resource.stringValue(), stream); + } + + @Override + public InputStream read(String resource) { + return null; + } + + @Override + public InputStream read(URI resource) { + return read(resource.stringValue()); + } + +} http://git-wip-us.apache.org/repos/asf/marmotta/blob/f59d008e/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 21989a3..70f1beb 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 @@ -23,6 +23,7 @@ import info.aduna.iteration.UnionIteration; import org.apache.marmotta.commons.vocabulary.DCTERMS; import org.apache.marmotta.commons.vocabulary.LDP; import org.apache.marmotta.platform.core.api.config.ConfigurationService; +import org.apache.marmotta.platform.ldp.api.LdpBinaryStoreService; import org.apache.marmotta.platform.ldp.api.LdpService; import org.apache.marmotta.platform.ldp.exceptions.InvalidModificationException; import org.apache.marmotta.platform.ldp.patch.InvalidPatchDocumentException; @@ -31,10 +32,7 @@ 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.openrdf.model.Literal; -import org.openrdf.model.Statement; -import org.openrdf.model.URI; -import org.openrdf.model.Value; +import org.openrdf.model.*; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.model.vocabulary.RDF; import org.openrdf.repository.RepositoryConnection; @@ -68,6 +66,15 @@ public class LdpServiceImpl implements LdpService { @Inject private ConfigurationService configurationService; + @Inject + private LdpBinaryStoreService binaryStore; + + private final URI ldpContext; + + public LdpServiceImpl() { + ldpContext = ValueFactoryImpl.getInstance().createURI(LDP.NAMESPACE); + } + private URI buildURI(String resource) { return ValueFactoryImpl.getInstance().createURI(resource); } @@ -79,7 +86,6 @@ public class LdpServiceImpl implements LdpService { @Override public boolean exists(RepositoryConnection connection, URI resource) throws RepositoryException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); return connection.hasStatement(resource, null, null, true, ldpContext); } @@ -90,8 +96,7 @@ public class LdpServiceImpl implements LdpService { @Override public List<Statement> getLdpTypes(RepositoryConnection connection, URI resource) throws RepositoryException { - final URI ldp = connection.getValueFactory().createURI(LDP.NAMESPACE); - return Iterations.asList(new FilterIteration<Statement, RepositoryException>(connection.getStatements(resource, RDF.TYPE, null, false, ldp)) { + return Iterations.asList(new FilterIteration<Statement, RepositoryException>(connection.getStatements(resource, RDF.TYPE, null, false, ldpContext)) { @Override protected boolean accept(Statement statement) { final Value object = statement.getObject(); @@ -107,7 +112,6 @@ public class LdpServiceImpl implements LdpService { @Override public void exportResource(RepositoryConnection connection, URI resource, OutputStream output, RDFFormat format) throws RepositoryException, RDFHandlerException { - URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); // TODO: this should be a little more sophisticated... // TODO: non-membership triples flag / Prefer-header RDFWriter writer = Rio.createWriter(format, output); @@ -129,12 +133,12 @@ public class LdpServiceImpl implements LdpService { @Override public boolean addResource(RepositoryConnection connection, URI container, URI resource, MediaType type, InputStream stream) throws RepositoryException, IOException, RDFParseException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); + ValueFactory valueFactory = connection.getValueFactory(); // Add container triples (Sec. 6.4.3) // container and meta triples! - Literal now = connection.getValueFactory().createLiteral(new Date()); + Literal now = valueFactory.createLiteral(new Date()); connection.add(container, RDF.TYPE, LDP.BasicContainer, ldpContext); connection.add(container, LDP.contains, resource, ldpContext); @@ -145,15 +149,15 @@ public class LdpServiceImpl implements LdpService { connection.add(resource, DCTERMS.created, now, ldpContext); connection.add(resource, DCTERMS.modified, now, ldpContext); - // TODO: No LDP-BC for now! - // Add the bodyContent log.trace("Content ({}) for new resource <{}>", type, resource); final RDFFormat rdfFormat = Rio.getParserFormatForMIMEType(type.toString(), RDFFormat.TURTLE); if (rdfFormat == null) { - log.debug("POST creates new LDP-BR with type {}", type); - log.warn("LDP-BR not (yet) supported!"); - throw new UnsupportedRDFormatException("No available parser for " + type.toString()); + 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 ? + //TODO: something else? + return binaryStore.store(resource, stream); //TODO: control exceptions } else { log.debug("POST creates new LDP-RR, data provided as {}", rdfFormat.getName()); @@ -171,7 +175,6 @@ public class LdpServiceImpl implements LdpService { @Override public EntityTag generateETag(RepositoryConnection connection, URI uri) throws RepositoryException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); final RepositoryResult<Statement> stmts = connection.getStatements(uri, DCTERMS.modified, null, true, ldpContext); try { // TODO: ETag is the last-modified date (explicitly managed) thus only weak. @@ -202,7 +205,6 @@ public class LdpServiceImpl implements LdpService { @Override public Date getLastModified(RepositoryConnection connection, URI uri) throws RepositoryException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); final RepositoryResult<Statement> stmts = connection.getStatements(uri, DCTERMS.modified, null, true, ldpContext); try { // TODO: ETag is the last-modified date (explicitly managed) thus only weak. @@ -229,11 +231,8 @@ public class LdpServiceImpl implements LdpService { @Override public void patchResource(RepositoryConnection connection, URI uri, InputStream patchData, boolean strict) throws RepositoryException, ParseException, InvalidModificationException, InvalidPatchDocumentException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); - final Literal now = connection.getValueFactory().createLiteral(new Date()); - log.trace("parsing patch"); List<PatchLine> patch = new RdfPatchParserImpl(patchData).parsePatch(); @@ -262,7 +261,6 @@ public class LdpServiceImpl implements LdpService { @Override public boolean deleteResource(RepositoryConnection connection, URI resource) throws RepositoryException { - final URI ldpContext = connection.getValueFactory().createURI(LDP.NAMESPACE); final Literal now = connection.getValueFactory().createLiteral(new Date()); // Delete corresponding containment and membership triples (Sec. 6.6.1)
