/* * Copyright 2009 Revelytix. * * 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.mulgara.resolver; import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.util.Map; import javax.activation.MimeType; import org.apache.log4j.Logger; import org.mulgara.content.Content; import org.mulgara.content.ContentHandler; import org.mulgara.content.ContentHandlerManager; import org.mulgara.query.Constraint; import org.mulgara.query.ConstraintImpl; import org.mulgara.query.LocalNode; import org.mulgara.query.QueryException; import org.mulgara.query.Variable; import org.mulgara.query.rdf.URIReferenceImpl; import org.mulgara.resolver.spi.DatabaseMetadata; import org.mulgara.resolver.spi.ResolverFactory; import org.mulgara.resolver.spi.Statements; import org.mulgara.resolver.spi.SystemResolver; import org.mulgara.resolver.spi.TuplesWrapperStatements; import org.mulgara.store.statement.StatementStore; import org.mulgara.store.tuples.Tuples; /** * An {@link Operation} that serializes the contents of an RDF graph to either * an output stream or a destination file. * * @created Jun 25, 2008 * @author Alex Hall * @copyright © 2008 <a href="http://www.revelytix.com">Revelytix, Inc.</a> * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a> */ class ExportOperation extends OutputOperation { private static final Logger logger = Logger.getLogger(ExportOperation.class); private final URI graphURI; private final Map<String,URI> prefixes; private final MimeType contentType; private final ContentHandlerManager contentManager; /** * Create an {@link Operation} which exports the contents of the specified RDF graph * to a URI or to an output stream. * * The database is not changed by this method. * If an {@link OutputStream} is supplied then the destinationURI is ignored. * * @param outputStream An output stream to receive the contents, may be * <code>null</code> if a <var>destinationURI</var> is specified * @param graphURI The URI of the graph to export, never <code>null</code>. * @param destinationURI The URI of the file to export into, may be * <code>null</code> if an <var>outputStream</var> is specified * @param initialPrefixes An optional set of user-supplied namespace prefix mappings; * may be <code>null</code> to use the generated namespace prefixes. */ public ExportOperation(OutputStream outputStream, URI graphURI, URI destinationURI, Map<String,URI> initialPrefixes, MimeType contentType, ContentHandlerManager contentManager) { super(outputStream, destinationURI); if (graphURI == null) { throw new IllegalArgumentException("Graph URI may not be null."); } if (contentManager == null) { throw new IllegalArgumentException("Content manager may not be null."); } this.graphURI = graphURI; this.contentType = contentType; this.prefixes = initialPrefixes; this.contentManager = contentManager; } /* (non-Javadoc) * @see org.mulgara.resolver.OutputOperation#execute(org.mulgara.resolver.OperationContext, org.mulgara.resolver.spi.SystemResolver, org.mulgara.resolver.spi.DatabaseMetadata) */ @Override public void execute(OperationContext operationContext, SystemResolver systemResolver, DatabaseMetadata metadata) throws Exception { // Verify that the graph is of a type that supports exports. long graph = systemResolver.localize(new URIReferenceImpl(graphURI)); ResolverFactory resolverFactory = operationContext.findModelResolverFactory(graph); if (resolverFactory.supportsExport()) { OutputStream os = getOutputStream(); assert os != null; boolean success = false; try { Content content = new StreamContent(os, destinationURI, contentType); ContentHandler handler = contentManager.getContentHandler(content); if (handler == null) throw new QueryException("Unable to determine content handler for " + destinationURI); // create a constraint to get all statements Variable[] vars = new Variable[] { StatementStore.VARIABLES[0], StatementStore.VARIABLES[1], StatementStore.VARIABLES[2] }; Constraint constraint = new ConstraintImpl(vars[0], vars[1], vars[2], new LocalNode(graph)); // Get all statements from the graph. Delegate to the operation context to do the security check. Tuples resolution = operationContext.resolve(constraint); Statements graphStatements = new TuplesWrapperStatements(resolution, vars[0], vars[1], vars[2]); // Do the writing. try { handler.serialize(graphStatements, content, systemResolver, prefixes); } finally { // This will close the wrapped resolution as well. graphStatements.close(); } success = true; } finally { // Clean up. if (os != null) { // Close the os if it exists. try { os.close(); } catch (IOException e) { if (success) throw e; // The export worked but we couldn't close the stream, so re-throw. else logger.info("Suppressing I/O exception closing failed export output", e); // Log and ignore. } } } } else { throw new QueryException("Graph " + graphURI + " does not support export."); } } }