/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): * SymbolicTransformation refactor contributed by Netymon Pty Ltd on behalf of * The Australian Commonwealth Government under contract 4500507038. * External XAResource contributed by Netymon Pty Ltd on behalf of Topaz * Foundation under contract. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.resolver; // Java 2 standard packages import java.io.*; import java.net.URI; import java.util.*; // Java 2 enterprise packages import javax.activation.MimeType; import javax.transaction.xa.XAResource; // Third party packages import org.apache.log4j.Logger; import org.jrdf.graph.*; // Local packages import org.mulgara.content.ContentHandlerManager; import org.mulgara.query.*; import org.mulgara.resolver.spi.*; import org.mulgara.rules.*; import org.mulgara.server.Session; import org.mulgara.transaction.TransactionManagerFactory; import org.mulgara.util.StackTrace; /** * A database session. * * @created 2004-04-26 * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a> * @copyright ©2004 <a href="http://www.tucanatech.com/">Tucana Technology, Inc</a> * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ class DatabaseSession implements Session { public static final boolean ASSERT_STATEMENTS = true; public static final boolean DENY_STATEMENTS = false; /** Logger. */ private static final Logger logger = Logger.getLogger(DatabaseSession.class.getName()); /** * Resolver factories that should be have access to their models cached. * This field is read-only. */ private final Set<ResolverFactory> cachedResolverFactorySet; /** * The list of all registered {@link ResolverFactory} instances. * Not used in this implementation. */ private final List<ResolverFactory> resolverFactoryList; /** * Map from URL protocol {@link String}s to the {@link ResolverFactory} which * handles external models using that protocol. */ private final Map<String,ResolverFactory> externalResolverFactoryMap; /** * Map from modelType {@link LocalNode}s to the {@link ResolverFactory} which * handles that model type. */ private final Map<URI,InternalResolverFactory> internalResolverFactoryMap; private final DatabaseMetadata metadata; /** Security adapters this instance should enforce. */ private final List<SecurityAdapter> securityAdapterList; /** Symbolic transformations this instance should apply. */ private final List<SymbolicTransformation> symbolicTransformationList; /** Persistent string pool. Not used, but passed in as a parameter. */ @SuppressWarnings("unused") private final ResolverSessionFactory resolverSessionFactory; /** Factory used to obtain the SystemResolver */ private final SystemResolverFactory systemResolverFactory; /** Factory used to obtain the SystemResolver */ private final ResolverFactory temporaryResolverFactory; /** Source of transactions. */ private final MulgaraTransactionManager transactionManager; private MulgaraTransactionFactory transactionFactory; private final MulgaraInternalTransactionFactory internalFactory; private final MulgaraExternalTransactionFactory externalFactory; /** the default maximum transaction duration */ private final long defaultTransactionTimeout; /** the default maximum transaction idle time */ private final long defaultIdleTimeout; /** the maximum transaction duration */ private long transactionTimeout; /** the maximum transaction idle time */ private long idleTimeout; /** The name of the rule loader to use */ private List<String> ruleLoaderClassNames; /** The registered {@link org.mulgara.content.ContentHandler} instances. */ private ContentHandlerManager contentHandlers; /** The temporary model type-URI. */ private final URI temporaryModelTypeURI; /** * Non-rule version of the constructor. Accepts all parameters except ruleLoaderClassName. */ DatabaseSession(MulgaraTransactionManager transactionManager, TransactionManagerFactory transactionManagerFactory, List<SecurityAdapter> securityAdapterList, List<SymbolicTransformation> symbolicTransformationList, ResolverSessionFactory resolverSessionFactory, SystemResolverFactory systemResolverFactory, ResolverFactory temporaryResolverFactory, List<ResolverFactory> resolverFactoryList, Map<String,ResolverFactory> externalResolverFactoryMap, Map<URI,InternalResolverFactory> internalResolverFactoryMap, DatabaseMetadata metadata, ContentHandlerManager contentHandlers, Set<ResolverFactory> cachedResolverFactorySet, URI temporaryModelTypeURI) throws ResolverFactoryException { this(transactionManager, transactionManagerFactory, securityAdapterList, symbolicTransformationList, resolverSessionFactory, systemResolverFactory, temporaryResolverFactory, resolverFactoryList, externalResolverFactoryMap, internalResolverFactoryMap, metadata, contentHandlers, cachedResolverFactorySet, temporaryModelTypeURI, 0, 0, null); } /** * Construct a database session. * * @param transactionManager the source of transactions for this session, * never <code>null</code> * @param transactionManagerFactory factory for internal jta transaction-manager * for this session, never <code>null</code> * @param securityAdapterList {@link List} of {@link SecurityAdapter}s to be * consulted before permitting operations, never <code>null</code> * @param symbolicTransformationList {@link List} of * {@link SymbolicTransformation}s, never <code>null</code> * @param resolverSessionFactory source of {@link ResolverSessionFactory}s, * never <code>null</code> * @param systemResolverFactory Source of {@link SystemResolver}s to manage * persistent models, for instance the system model (<code>#</code>); never * <code>null</code> * @param temporaryResolverFactory Source of {@link Resolver}s to manage * models which only last the duration of a transaction, for instance the * contents of external RDF/XML documents; never <code>null</code> * @param resolverFactoryList the list of registered {@link ResolverFactory} * instances to use for constraint resolution, never <code>null</code> * @param externalResolverFactoryMap map from URL protocol {@link String}s * to {@link ResolverFactory} instances for models accessed via that * protocol, never <code>null</code> * @param internalResolverFactoryMap map from model type {@link LocalNode}s * to {@link ResolverFactory} instances for that model type, never * <code>null</code> * @param metadata even more parameters from the parent {@link Database}, * never <code>null</code> * @param contentHandlers contains the list of valid registered content handles * never <code>null</code> * @param temporaryModelTypeURI the URI of the model type to use to cache * external models * @param transactionTimeout the default number of milli-seconds before transactions * time out, or zero to take the <var>transactionManagerFactory</var>'s default; * never negative * @param idleTimeout the default number of milli-seconds a transaction may be idle * before it is timed out, or zero to take the <var>transactionManagerFactory</var>'s * default; never negative * @param ruleLoaderClassNames the rule-loader classes to use; may be null * @throws IllegalArgumentException if any argument is <code>null</code> */ DatabaseSession(MulgaraTransactionManager transactionManager, TransactionManagerFactory transactionManagerFactory, List<SecurityAdapter> securityAdapterList, List<SymbolicTransformation> symbolicTransformationList, ResolverSessionFactory resolverSessionFactory, SystemResolverFactory systemResolverFactory, ResolverFactory temporaryResolverFactory, List<ResolverFactory> resolverFactoryList, Map<String,ResolverFactory> externalResolverFactoryMap, Map<URI,InternalResolverFactory> internalResolverFactoryMap, DatabaseMetadata metadata, ContentHandlerManager contentHandlers, Set<ResolverFactory> cachedResolverFactorySet, URI temporaryModelTypeURI, long transactionTimeout, long idleTimeout, List<String> ruleLoaderClassNames) throws ResolverFactoryException { if (logger.isDebugEnabled()) { logger.debug("Constructing DatabaseSession: externalResolverFactoryMap=" + externalResolverFactoryMap + " internalResolverFactoryMap=" + internalResolverFactoryMap + " metadata=" + metadata); } // Validate parameters if (transactionManager == null) { throw new IllegalArgumentException("Null 'transactionManager' parameter"); } else if (transactionManagerFactory == null) { throw new IllegalArgumentException("Null 'transactionManagerFactory' parameter"); } else if (securityAdapterList == null) { throw new IllegalArgumentException("Null 'securityAdapterList' parameter"); } else if (symbolicTransformationList == null) { throw new IllegalArgumentException("Null 'symbolicTransformationList' parameter"); } else if (resolverSessionFactory == null) { throw new IllegalArgumentException("Null 'resolverSessionFactory' parameter"); } else if (systemResolverFactory == null) { throw new IllegalArgumentException("Null 'systemResolverFactory' parameter"); } else if (temporaryResolverFactory == null) { throw new IllegalArgumentException("Null 'temporaryResolverFactory' parameter"); } else if (resolverFactoryList == null) { throw new IllegalArgumentException("Null 'resolverFactoryList' parameter"); } else if (externalResolverFactoryMap == null) { throw new IllegalArgumentException("Null 'externalResolverFactoryMap' parameter"); } else if (internalResolverFactoryMap == null) { throw new IllegalArgumentException("Null 'internalResolverFactoryMap' parameter"); } else if (contentHandlers == null) { throw new IllegalArgumentException("Null 'contentHandlers' parameter"); } else if (metadata == null) { throw new IllegalArgumentException("Null 'metadata' parameter"); } else if (cachedResolverFactorySet == null) { throw new IllegalArgumentException("Null 'cachedResolverFactorySet' parameter"); } else if (temporaryModelTypeURI == null) { throw new IllegalArgumentException("Null 'temporaryModelTypeURI' parameter"); } else if (transactionTimeout < 0) { throw new IllegalArgumentException("negative 'transactionTimeout' parameter"); } else if (idleTimeout < 0) { throw new IllegalArgumentException("negative 'idleTimeout' parameter"); } else if (ruleLoaderClassNames == null) { ruleLoaderClassNames = Collections.emptyList(); } // Initialize fields this.transactionManager = transactionManager; this.securityAdapterList = securityAdapterList; this.symbolicTransformationList = symbolicTransformationList; this.resolverSessionFactory = resolverSessionFactory; this.systemResolverFactory = systemResolverFactory; this.temporaryResolverFactory = temporaryResolverFactory; this.resolverFactoryList = resolverFactoryList; this.externalResolverFactoryMap = externalResolverFactoryMap; this.internalResolverFactoryMap = internalResolverFactoryMap; this.metadata = metadata; this.contentHandlers = contentHandlers; this.cachedResolverFactorySet = cachedResolverFactorySet; this.temporaryModelTypeURI = temporaryModelTypeURI; this.defaultTransactionTimeout = transactionTimeout; this.defaultIdleTimeout = idleTimeout; this.ruleLoaderClassNames = ruleLoaderClassNames; this.transactionFactory = null; this.externalFactory = new MulgaraExternalTransactionFactory(this, transactionManager); this.internalFactory = new MulgaraInternalTransactionFactory(this, transactionManager, transactionManagerFactory); this.transactionTimeout = defaultTransactionTimeout; this.idleTimeout = defaultIdleTimeout; if (logger.isTraceEnabled()) logger.trace("Constructed DatabaseSession"); } // // Internal methods required for database initialisation. // /** * Used by Database *only* to bootstrap the system model on DB startup. */ long bootstrapSystemModel(DatabaseMetadataImpl metadata) throws QueryException { logger.debug("Bootstrapping System Graph"); BootstrapOperation operation = new BootstrapOperation(metadata); execute(operation, "Failed to bootstrap system-model"); systemResolverFactory.setDatabaseMetadata(metadata); return operation.getResult(); } /** * Preallocate a local node number for an RDF {@link Node}. * * This method is used only by {@link DatabaseResolverFactoryInitializer} * and {@link DatabaseSecurityAdapterInitializer}. * * @param node an RDF node * @return the preallocated local node number corresponding to the * <var>node</var>, never {@link org.mulgara.store.nodepool.NodePool#NONE} * @throws QueryException if the local node number can't be obtained */ long preallocate(Node node) throws QueryException { PreallocateOperation preOp = new PreallocateOperation(node); execute(preOp, "Failure to preallocated " + node); return preOp.getResult(); } // // Methods implementing Session // public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException { modify(modelURI, statements, ASSERT_STATEMENTS); } public void insert(URI modelURI, Query query) throws QueryException { modify(modelURI, query, ASSERT_STATEMENTS); } public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException { modify(modelURI, statements, DENY_STATEMENTS); } public void delete(URI modelURI, Query query) throws QueryException { modify(modelURI, query, DENY_STATEMENTS); } /** * Backup all the data on the server. The database is not changed by this method. * @param destinationURI The URI of the file to backup into. * @throws QueryException if the backup cannot be completed. */ public void backup(URI destinationURI) throws QueryException { this.backup(null, destinationURI); } /** * Backup all the data on the specified server to an output stream. * The database is not changed by this method. * @param outputStream The stream to receive the contents * @throws QueryException if the backup cannot be completed. */ public void backup(OutputStream outputStream) throws QueryException { this.backup(outputStream, null); } /** * Export the data in the specified graph. The database is not changed by this method. * @param graphURI The URI of the graph to export. * @param destinationURI The URI of the file to export into. * @throws QueryException if the export cannot be completed. */ public void export(URI graphURI, URI destinationURI) throws QueryException { this.export(null, graphURI, destinationURI, null, null); } /** * Export the data in the specified graph using pre-defined namespace prefixes. * The database is not changed by this method. * @param graphURI The URI of the graph to export. * @param destinationURI The URI of the file to export into. * @param prefixes An optional mapping for pre-populating the RDF/XML namespace prefixes. * @throws QueryException if the export cannot be completed. */ public void export(URI graphURI, URI destinationURI, Map<String,URI> prefixes) throws QueryException { this.export(null, graphURI, destinationURI, prefixes, null); } /** * Export the data in the specified graph to an output stream. * The database is not changed by this method. * @param graphURI The URI of the server or model to export. * @param outputStream The stream to receive the contents * @throws QueryException if the export cannot be completed. */ public void export(URI graphURI, OutputStream outputStream, MimeType contentType) throws QueryException { this.export(outputStream, graphURI, null, null, contentType); } /** * Export the data in the specified graph to an output stream using pre-defined namespace prefixes. * The database is not changed by this method. * @param graphURI The URI of the server or model to export. * @param outputStream The stream to receive the contents * @param prefixes An optional mapping for pre-populating the RDF/XML namespace prefixes. * @throws QueryException if the export cannot be completed. */ public void export(URI graphURI, OutputStream outputStream, Map<String,URI> prefixes, MimeType contentType) throws QueryException { this.export(outputStream, graphURI, null, prefixes, contentType); } /** * Restore all the data on the server. If the database is not * currently empty then the current contents of the database will be replaced * with the content of the backup file when this method returns. * @param sourceURI The URI of the backup file to restore from. * @throws QueryException if the restore cannot be completed. */ public void restore(URI sourceURI) throws QueryException { this.restore(null, sourceURI); } /** * Restore all the data on the server. If the database is not * currently empty then the current contents of the database will be replaced * with the content of the backup file when this method returns. * @param inputStream a client supplied inputStream to obtain the restore * content from. If null assume the sourceURI has been supplied. * @param sourceURI The URI of the backup file to restore from. * @throws QueryException if the restore cannot be completed. */ public void restore(InputStream inputStream, URI sourceURI) throws QueryException { execute(new RestoreOperation(inputStream, sourceURI), "Unable to restore from " + sourceURI); for (ResolverFactory resFactory: resolverFactoryList) { createDefaultGraphs(resFactory.getDefaultGraphs()); } } /** * Execute a SELECT query on the database. * @see org.mulgara.server.Session#query(org.mulgara.query.Query) */ public Answer query(Query query) throws QueryException { if (logger.isDebugEnabled()) logger.debug("QUERY: " + query); QueryOperation queryOperation = new QueryOperation(query, this); execute(queryOperation, "Query failed"); return queryOperation.getAnswer(); } /** * Tests the database to see if a query will return any data. * @see org.mulgara.server.Session#query(org.mulgara.query.AskQuery) */ public boolean query(AskQuery query) throws QueryException { if (logger.isDebugEnabled()) logger.debug("ASK QUERY: " + query); QueryOperation queryOperation = new QueryOperation(query, this); execute(queryOperation, "Query failed"); return ((BooleanAnswer)queryOperation.getAnswer()).getResult(); } /** * Queries the database for data that will be structured as a graph. * @see org.mulgara.server.Session#query(org.mulgara.query.ConstructQuery) */ public GraphAnswer query(ConstructQuery query) throws QueryException { if (logger.isDebugEnabled()) logger.debug("CONSTRUCT QUERY: " + query); QueryOperation queryOperation = new QueryOperation(query, this); execute(queryOperation, "Query failed"); return (GraphAnswer)queryOperation.getAnswer(); } public List<Answer> query(List<Query> queryList) throws QueryException { if (logger.isDebugEnabled()) { StringBuffer log = new StringBuffer("QUERYING LIST: "); for (int i = 0; i < queryList.size(); i++) log.append(queryList.get(i)); logger.debug(log.toString()); } QueryOperation queryOperation = new QueryOperation(queryList, this); execute(queryOperation, "Failed list query"); return queryOperation.getAnswerList(); } public void createModel(URI modelURI, URI modelTypeURI) throws QueryException { if (logger.isDebugEnabled()) logger.debug("Creating Graph " + modelURI + " with type " + modelTypeURI); execute(new CreateGraphOperation(modelURI, modelTypeURI), "Could not commit creation of model " + modelURI + " of type " + modelTypeURI); } public boolean createDefaultGraph(URI modelURI, URI modelTypeURI) throws QueryException { if (logger.isDebugEnabled()) logger.debug("Creating Graph " + modelURI + " with type " + modelTypeURI + " in the system graph"); CreateDefaultGraphOperation op = new CreateDefaultGraphOperation(modelURI, modelTypeURI); execute(op, "Could not commit creation of model " + modelURI + " of type " + modelTypeURI); return op.getResult(); } public void removeModel(URI modelURI) throws QueryException { if (logger.isDebugEnabled()) logger.debug("REMOVE MODEL: " + modelURI); if (modelURI == null) throw new IllegalArgumentException("Null 'modelURI' parameter"); execute(new RemoveGraphOperation(modelURI), "Unable to remove " + modelURI); } public boolean modelExists(URI modelURI) throws QueryException { GraphExistsOperation operation = new GraphExistsOperation(modelURI); execute(operation, "Failed to determine model existence"); return operation.getResult(); } /** * Define the contents of a model. * @param uri the {@link URI} of the model to be redefined * @param sourceUri the new content for the model * @return RETURNED VALUE TO DO * @throws QueryException if the model can't be modified */ public synchronized long setModel(URI uri, URI sourceUri) throws QueryException { return this.setModel(null, uri, sourceUri, null); } /** * Define the contents of a model via an inputstream * @param inputStream a remote inputstream * @param destinationUri the {@link URI} of the graph to be redefined * @param sourceUri the new content for the graph * @return The number of statements loaded into the graph * @throws QueryException if the model can't be modified */ public synchronized long setModel(InputStream inputStream, URI destinationUri, URI sourceUri, MimeType contentType) throws QueryException { if (logger.isDebugEnabled()) { logger.debug("SET-MODEL " + destinationUri + " to " + sourceUri + " from " + inputStream); } // Validate parameters if (destinationUri == null) { throw new IllegalArgumentException("Must provide a destination graph URI."); } if (sourceUri == null && (contentType == null || inputStream == null)) { throw new IllegalArgumentException("Must provide either a source URI or a source input stream/content type."); } assert sourceUri != null || contentType != null; // Perform the operation SetGraphOperation op = new SetGraphOperation(sourceUri, destinationUri, inputStream, contentType, contentHandlers); execute(op, "Unable to load " + sourceUri + " into " + destinationUri); return op.getStatementCount(); } /** * {@inheritDoc} */ public RulesRef buildRules(URI ruleModel, GraphExpression baseModel, URI destModel) throws QueryException, org.mulgara.rules.InitializerException { if (logger.isDebugEnabled()) logger.debug("BUILD RULES: " + ruleModel); BuildRulesOperation operation = new BuildRulesOperation(ruleLoaderClassNames, ruleModel, baseModel, destModel); execute(operation, "Failed to create rules"); return operation.getResult(); } /** * {@inheritDoc} */ public void applyRules(RulesRef rulesRef) throws QueryException { execute(new ApplyRulesOperation(rulesRef), "Unable to apply rules"); } public void setAutoCommit(boolean autoCommit) throws QueryException { if (logger.isDebugEnabled()) logger.debug("setAutoCommit(" + autoCommit + ") called."); assertInternallyManagedXA(); try { internalFactory.setAutoCommit(autoCommit); } catch (MulgaraTransactionException em) { throw new QueryException("Error setting autocommit", em); } } public void commit() throws QueryException { logger.debug("Committing transaction"); assertInternallyManagedXA(); try { internalFactory.commit(); } catch (MulgaraTransactionException em) { throw new QueryException("Error performing commit", em); } } public void rollback() throws QueryException { logger.debug("Rollback transaction"); assertInternallyManagedXA(); try { internalFactory.rollback(); } catch (MulgaraTransactionException em) { throw new QueryException("Error performing rollback", em); } } public void close() throws QueryException { logger.debug("Closing session"); try { if (transactionFactory != null) transactionFactory.closingSession(); } catch (MulgaraTransactionException em) { logger.error("Error force-closing session", em); throw new QueryException("Error force-closing session.", em); } finally { try { transactionManager.closingSession(this); } catch (MulgaraTransactionException em2) { logger.error("Error force-closing session", em2); throw new QueryException("Error force-closing session.", em2); } } } public boolean isLocal() { return true; } public void login(URI securityDomain, String user, char[] password) { if (logger.isTraceEnabled()) logger.trace("Login of " + user + " to " + securityDomain); if (securityDomain.equals(metadata.getSecurityDomainURI())) { // Propagate the login event to the security adapters for (SecurityAdapter adapter: securityAdapterList) { adapter.login(user, password); } } } /** * Backup all the data on the specified server to a URI or an output stream. * The database is not changed by this method. * * If an outputstream is supplied then the destinationURI is ignored. * * @param outputStream Optional output stream to receive the contents * @param destinationURI Option URI of the file to backup into. * @throws QueryException if the backup cannot be completed. */ private synchronized void backup(OutputStream outputStream, URI destinationURI) throws QueryException { execute(new BackupOperation(outputStream, destinationURI), "Unable to backup to " + destinationURI); } /** * Export the data on the specified graph to a URI or an output stream. * The database is not changed by this method. * * If an outputstream is supplied then the destinationURI is ignored. * * @param outputStream Optional output stream to receive the contents * @param graphURI The URI of the graph to export. * @param destinationURI Optional URI of the file to export into. * @param initialPrefixes An optional set of user-supplied namespace prefix mappings; * may be <code>null</code> to use the generated namespace prefixes. * @param contentType TODO * @throws QueryException if the export cannot be completed. */ private synchronized void export(OutputStream outputStream, URI graphURI, URI destinationURI, Map<String,URI> initialPrefixes, MimeType contentType) throws QueryException { execute(new ExportOperation(outputStream, graphURI, destinationURI, initialPrefixes, contentType, contentHandlers), "Unable to export " + graphURI); } // // Internal utility methods. // protected void modify(URI modelURI, Set<? extends Triple> statements, boolean insert) throws QueryException { if (logger.isDebugEnabled()) logger.debug("Modifying (ins:" + insert + ") : " + modelURI); if (logger.isTraceEnabled()) logger.trace("Modifying statements: " + statements); execute(new ModifyGraphOperation(modelURI, statements, insert), "Could not commit modify"); } private void modify(URI modelURI, Query query, boolean insert) throws QueryException { if (logger.isDebugEnabled()) { logger.debug((insert ? "INSERT" : "DELETE") + " QUERY: " + query + " into " + modelURI); } execute(new ModifyGraphOperation(modelURI, query, insert, this), "Unable to modify " + modelURI); } /** * Execute an {@link Operation}. * * @param operation the {@link Operation} to execute * @throws QueryException if the <var>operation</var> fails */ private void execute(Operation operation, String errorString) throws QueryException { ensureTransactionFactorySelected(); try { MulgaraTransaction transaction = transactionFactory.getTransaction(operation.isWriteOperation()); transaction.execute(operation, metadata); } catch (MulgaraTransactionException em) { if (logger.isDebugEnabled()) logger.debug("Error executing operation: " + errorString, em); throw new QueryException(errorString + ": " + StackTrace.getReasonMessage(em), em); } } public DatabaseOperationContext newOperationContext(boolean writing) throws QueryException { return new DatabaseOperationContext( cachedResolverFactorySet, externalResolverFactoryMap, internalResolverFactoryMap, metadata, securityAdapterList, temporaryModelTypeURI, temporaryResolverFactory, symbolicTransformationList, systemResolverFactory, writing); } /** * Creates a series of default graphs for a resolver. * @param graphs An array of the graph names and types to create. May be null. * @return <code>true</code> if any graphs were created, <code>false</code> otherwise. * @throws QueryException If it was not possible to detect if the graph already existed. */ boolean createDefaultGraphs(ResolverFactory.Graph[] graphs) throws QueryException { boolean result = false; if (graphs != null) { for (ResolverFactory.Graph graph: graphs) { result = result || createDefaultGraph(graph.getGraph(), graph.getType()); } } return result; } private void ensureTransactionFactorySelected() throws QueryException { if (transactionFactory == null) assertInternallyManagedXA(); } private void assertInternallyManagedXA() throws QueryException { if (transactionFactory == null) { transactionFactory = internalFactory; } else if (transactionFactory != internalFactory) { throw new QueryException("Attempt to use internal transaction control in externally managed session"); } } private void assertExternallyManagedXA() throws QueryException { if (transactionFactory == null) { transactionFactory = externalFactory; } else if (transactionFactory != externalFactory) { throw new QueryException("Attempt to use external transaction control in internally managed session"); } } public XAResource getXAResource() throws QueryException { assertExternallyManagedXA(); return externalFactory.getXAResource(true); } public XAResource getReadOnlyXAResource() throws QueryException { assertExternallyManagedXA(); return externalFactory.getXAResource(false); } public void setIdleTimeout(long millis) { idleTimeout = millis > 0 ? millis : defaultIdleTimeout; } public void setTransactionTimeout(long millis) { transactionTimeout = millis > 0 ? millis : defaultTransactionTimeout; } public long getIdleTimeout() { return idleTimeout; } public long getTransactionTimeout() { return transactionTimeout; } public boolean ping() { return true; } }