/* * Copyright 2009 DuraSpace. * * 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.query.operation; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import javax.activation.MimeType; import org.apache.log4j.Logger; import org.mulgara.connection.Connection; import org.mulgara.connection.Connection.SessionOp; import org.mulgara.query.QueryException; import org.mulgara.query.rdf.Mulgara; import org.mulgara.server.Session; /** * Represents a command to load data into a model. * * @created Aug 19, 2007 * @author Paula Gearon * @copyright © 2007 <a href="mailto:pgearon@users.sourceforge.net">Paula Gearon</a> * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a> */ public class Load extends DataInputTx { /** The logger */ static final Logger logger = Logger.getLogger(Load.class.getName()); /** The type of data that may be in a stream. */ private final MimeType contentType; /** * Build a load operation, loading data from one URI into a graph specified by another URI. * @param sourceUri The URI of the source of the RDF data. * @param destinationUri The URI of the graph to receive the data. * @param local Set to <code>true</code> to indicate that the source is on the client system. */ public Load(URI sourceUri, URI destinationUri, boolean local) { super(sourceUri, destinationUri, destinationUri, local); // Validate arguments. if (destinationUri == null) throw new IllegalArgumentException("Need a valid destination graph URI"); contentType = null; } /** * Builds a load operation which will load data from the supplied input stream into the given destination graph. * One or both of content type and source URI must be provided in order for the server to determine * the format of the content (RDF/XML, Turtle, etc). If the source URI is given, it will be used as * the base URI for resolving relative URI references when parsing the content. * @param destinationUri The URI of the graph to receive the data. * @param stream The local input stream that is the source of the data to load. * @param contentType The MIME content type of the data, if known. If present, the MIME type will take * precedence when selecting the parser to use. * @param sourceUri The source URI; this is not actually de-referenced, but if present will be used as * the base URI for resolving relative URIs parsed from the content. If the content type is null * or does not match a configured handler then the filename extension from the source URI will * be used to select a parser. */ public Load(URI destinationUri, InputStream stream, MimeType contentType, URI sourceUri) { super(sourceUri, destinationUri, destinationUri, true); // Validate arguments. if (destinationUri == null) throw new IllegalArgumentException("Need a valid destination graph URI"); this.contentType = contentType; setOverrideInputStream(stream); } /** * Alternate constructor for creating a load operation whose source will be a local input stream, * without providing a base URI (this means relative URI references in the file will not be resolved). * @param graphURI The URI of the graph to receive the data. * @param stream The local input stream that is the source of data to load. * @param contentType the content type for the stream. */ public Load(URI graphURI, InputStream stream, MimeType contentType) { this(graphURI, stream, contentType, (URI)null); } /** * Alternate constructor for creating a load operation whose source will be a local input stream, * and a filename has been provided. The filename will be used to construct the base URI for parsing. * @param graphURI The URI of the graph to receive the data. * @param stream The local input stream that is the source of data to load. * @param contentType the content type for the stream. * @param file A string form of the uri of the file to load; will be used to construct a base URI. */ public Load(URI graphURI, InputStream stream, MimeType contentType, String file) { this(graphURI, stream, contentType, toUri(file)); } /** * Load the data into the destination graph through the given connection. * @param conn The connection to load the data over. * @return The number of statements that were inserted. */ public Object execute(Connection conn) throws QueryException { URI src = getSource(); URI dest = getDestination(); if (isLocal() && !conn.isRemote() && overrideInputStream == null) { logger.error("Used a LOCAL modifier when loading <" + src + "> to <" + dest + "> on a non-remote server."); throw new QueryException("LOCAL modifier is not valid for LOAD command when not using a client-server connection."); } try { long stmtCount = isLocal() ? sendMarshalledData(conn, true) : doTx(conn, getSource()); if (logger.isDebugEnabled()) logger.debug("Loaded " + stmtCount + " statements from " + src + " into " + dest); if (stmtCount > 0L) setResultMessage("Successfully loaded " + stmtCount + " statements from " + (src != null ? src : "input stream") + " into " + dest); else setResultMessage("WARNING: No valid RDF statements found in " + (src != null ? src : "input stream")); return stmtCount; } catch (IOException ex) { logger.error("Error attempting to load : " + src, ex); throw new QueryException("Error attempting to load : " + src, ex); } } /* (non-Javadoc) * @see org.mulgara.query.operation.DataInputTx#getExecutable(java.io.InputStream) */ @Override protected SessionOp<Long,QueryException> getExecutable(final InputStream inputStream) { return new SessionOp<Long,QueryException>() { public Long fn(Session session) throws QueryException { return session.setModel(inputStream, getDestination(), getSource(), contentType); } }; } /* (non-Javadoc) * @see org.mulgara.query.operation.DataInputTx#getExecutable(java.net.URI) */ @Override protected SessionOp<Long,QueryException> getExecutable(final URI src) { return new SessionOp<Long,QueryException>() { public Long fn(Session session) throws QueryException { return session.setModel(getDestination(), src); } }; } /** * Get the text of the command, or generate a virtual command if no text was parsed. * @return The query that created this command, or a generated query if no query exists. */ public String getText() { String text = super.getText(); if (text == null || text.length() == 0) text = "load <" + getSource() + "> into <" + getDestination() + ">"; return text; } /** * Attempt to turn a filename into a URI. If unsuccessful return null. * @param filename The path for a file. * @return The URI for the file, or null if the filename could not be converted. */ private static URI toUri(String filename) { if (filename == null) return null; try { return new URI(Mulgara.VIRTUAL_NS + filename); } catch (URISyntaxException e) { return null; } } }