/*
* 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.connection;
import java.net.URI;
import org.mulgara.query.Answer;
import org.mulgara.query.AskQuery;
import org.mulgara.query.BooleanAnswer;
import org.mulgara.query.Query;
import org.mulgara.query.QueryException;
import org.mulgara.query.TuplesException;
import org.mulgara.query.operation.Command;
import org.mulgara.query.operation.Load;
import org.mulgara.server.Session;
import org.mulgara.util.functional.Fn1E;
/**
* This interface abstracts connections to a server, holding any information relevant to that
* connection. For those operations that are to be performed on a server, this interface
* is used to send the operations. Other operations can be kept local, but the mechanism
* appears the same to the user, thereby abstracting away the interaction that each command
* has with servers.
*
* The preferred method for instantiating a Connection is using the {@link ConnectionFactory}
* class. The ConnectionFactory allows for re-use of underlying resources when connecting to
* servers using the server URI. It is synchronized for use by multiple clients in a
* multi-threaded environment; connections obtained concurrently by separate clients from the
* same factory will not interfere with each other. Note that while the factory is synchronized
* for concurrent access, the connection itself is not and should only be accessed by a single
* thread. When a client connection is no longer in use, its underlying resources are returned
* to the factory for re-use by other clients.
*
* Connections which are no longer in use should be closed using the {@link #close()} method.
* Calling this method allows the underlying session backing the connection to be released back
* to the factory for re-use by other clients. This will result in increased performance in an
* environment where there are many short-lived connections in use. Since the session stores
* credentials that are passed to the connection, a factory should only be used to cache
* connections in a single-user environment. Alternatively, the {@link #dispose()} method may
* be used to explicitly destroy the underlying session, in which case it will not be cached and
* re-used by the factory. Calling either {@link #close()} or {@link #dispose()} will cause the
* connection to be invalidated, and any subsequent attempts to execute an operation on it will
* cause an exception to be thrown.
*
* {@link org.mulgara.query.operation.Command}s to be issued may be executed with a Connection
* as a parameter, or can be passed to a Connection. The appropriate use depends on the usage.
* When creating commands in code, the preferred idiom is to pass to a Connection. For instance:
* <pre><code>
* ConnectionFactory factory = new ConnectionFactory();
* Connection conn = factory.newConnection(URI.create("rmi://localhost/server1"));
*
* URI graph = URI.create("rmi://localhost/server1#graph");
* Command create = new CreateGraph(graph);
* Command load = new Load(new File("data.rdf").toURI(), graph, false);
* Command query = new TqlInterpreter().parseCommand(queryString);
*
* conn.execute(create);
* conn.execute(load);
* Answer answer = conn.execute(query);
* </code></pre>
*
* This mechanism has the advantage of returning the appropriate type for each type of command
* For instance, {@link Query} commands return an {@link Answer}, while most other commands
* return a status string.
*
* Alternatively, if the commands are being generated by a query language parser, then the command
* operation should be picked up via polymorphism by calling execute on the command instead.
* <pre><code>
* ConnectionFactory factory = new ConnectionFactory();
* Connection conn = factory.newConnection(URI.create("rmi://localhost/server1"));
*
* Interpreter interpreter = new TqlInterpreter();
* Command cmd = interpreter.parseCommand(commandString);
*
* Object result = cmd.execute(conn);
* </code></pre>
*
* @created 2007-09-25
* @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 interface Connection {
/**
* Give login credentials and security domain to the current session. This should only be needed
* once since the session does not change.
* @param securityDomainUri The security domain for the login.
* @param user The username.
* @param password The password for the given username.
*/
public void setCredentials(URI securityDomainUri, String user, char[] password);
/**
* Give login credentials for the current security domain to the current session.
* This should only be needed
* once since the session does not change.
* @param user The username.
* @param password The password for the given username.
*/
public void setCredentials(String user, char[] password);
/**
* @return the session
* @deprecated Clients should not access the session directly; use {@link #execute(SessionOp)} instead.
*/
public Session getSession();
/**
* Tests if this connection is over a network protocol.
* @return <code>true</code> if this connection is being executed over a network protocol.
*/
public boolean isRemote();
/**
* Starts and commits transactions on this connection, by turning the autocommit
* flag on and off.
* @param autoCommit <code>true</code> if the flag is to be on.
* @throws QueryException The session could not change state.
*/
public void setAutoCommit(boolean autoCommit) throws QueryException;
/**
* @return the autoCommit value
*/
public boolean getAutoCommit();
/**
* Closes the current connection.
*/
public void close() throws QueryException;
/**
* Closes the current connection, disposing of any underlying resources rather
* than returning them to the factory for re-use.
*/
public void dispose() throws QueryException;
// Central execution of Command operations
/**
* Generic command execution method.
* @param cmd The command to execute.
* @return A status message
* @throws Exception A general exception catchall
*/
public String execute(Command cmd) throws Exception;
/**
* Executes the given operation synchronously and atomically against the session underlying this connection.
* Note that the session passed to the operation may be <tt>null</tt> in the case of
* a dummy local connection.
* @param <T> The type of object returned by the operation.
* @param <E> The type of exception thrown by the operation.
* @param cmd The operation to be executed.
* @return The result of the operation.
* @throws E If an exception occurred executing the operation.
*/
public <T,E extends Exception> T execute(SessionOp<T,E> cmd) throws E;
/**
* Loads data from a file or URL
* @param cmd The command to load the data
* @return The number of loaded statements
*/
public Long execute(Load cmd) throws QueryException;
/**
* Issues a query on the connection.
* @param cmd The command to issue the query.
* @return An Answer with the query results.
*/
public Answer execute(Query cmd) throws QueryException, TuplesException;
/**
* Issues an ASK query on the connection.
* @param cmd The ASK command to issue the query.
* @return A BooleanAnswer with the true/false result of the query.
*/
public BooleanAnswer execute(AskQuery cmd) throws QueryException, TuplesException;
/**
* Cancels the operation currently executing against this connection's session, if
* there is one. The operation will be canceled using the {@link Thread#interrupt()} method.
*/
public void cancel();
/**
* An operation that can be executed against a session and throw an exception.
* @param <T> The result type of the operation.
* @param <E> The type of exception thrown by the operation.
*/
public interface SessionOp<T,E extends Exception> extends Fn1E<Session,T,E> {}
}