[Mulgara-svn] r723 - in branches/mgr-61-sparql: . docs/site-src/design jxdata/iTQL jxdata/iTQL/backup_restore jxdata/iTQL/create_drop jxdata/iTQL/data_types jxdata/iTQL/data_types/binary/base64Binary jxdata/iTQL/data_types/binary/hexBinary jxdata/iTQL/data_types/boolean jxdata/iTQL/data_types/gDates jxdata/iTQL/filesystem jxdata/iTQL/fulltext_queries jxdata/iTQL/insert jxdata/iTQL/node_types jxdata/iTQL/parser jxdata/iTQL/prefix jxdata/iTQL/rdfs/rdfs-container-membership-superProperty jxdata/iTQL/rdfs/rdfs-domain-and-range jxdata/iTQL/rdfs/rdfs-no-cycles-in-subClassOf jxdata/iTQL/rdfs/rdfs-no-cycles-in-subPropertyOf jxdata/iTQL/rdfs/rdfs-subPropertyOf-semantics jxdata/iTQL/rdfs/statement-entailment jxdata/iTQL/standard_queries jxdata/iTQL/transactions lib src/jar/ant-task/java/org/mulgara/ant/task/rdf src/jar/client-jrdf/java/org/mulgara/client/jrdf/test src/jar/config src/jar/content-mbox/java/org/mulgara/content/mbox src/jar/content-mp3/java/org/mulgara/content/mp3 src/jar/content-n3/java/org/mulgara/content/n3 src/jar/content-rdfxml/java/org/mulgara/content/rdfxml src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/writer src/jar/content-rio/java/org/mulgara/content/rio src/jar/demo-mp3/java/org/mulgara/demo/mp3/swing src/jar/descriptor/src/java/org/mulgara/descriptor src/jar/itql src/jar/itql/java/org/mulgara/itql src/jar/itql/sablecc src/jar/krule src/jar/krule/java/org/mulgara/krule src/jar/query/java/org/mulgara/connection src/jar/query/java/org/mulgara/parser src/jar/query/java/org/mulgara/query src/jar/query/java/org/mulgara/query/operation src/jar/query/java/org/mulgara/query/rdf src/jar/query/java/org/mulgara/server src/jar/rdql src/jar/rdql/java/org/mulgara/rdql src/jar/resolver src/jar/resolver/java/org/mulgara/resolver src/jar/resolver-distributed/java/org/mulgara/resolver/distributed src/jar/resolver-filesystem/java/org/mulgara/resolver/filesystem src/jar/resolver-http/java/org/mulgara/resolver/http src/jar/resolver-lucene/java/org/mulgara/resolver/lucene src/jar/resolver-memory/java/org/mulgara/resolver/memory src/jar/resolver-spi/java/org/mulgara/resolver/spi src/jar/resolver-store/java/org/mulgara/resolver/store src/jar/resolver-store/java/org/mulgara/store/statement/xa src/jar/resolver-test/java/org/mulgara/resolver/test src/jar/resolver-view/java/org/mulgara/resolver/view src/jar/resolver-xsd/java/org/mulgara/resolver/xsd src/jar/rules/java/org/mulgara/rules src/jar/server/java/org/mulgara/server src/jar/server-beep/java/org/mulgara/server/beep src/jar/server-http src/jar/server-http/java/org/mulgara/server/http src/jar/server-rmi/java/org/mulgara/server/rmi src/jar/sparql-protocol/java/org/mulgara/sparql/protocol src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa src/jar/store-stringpool/java/org/mulgara/store/stringpool src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa src/jar/store-xa/java/org/mulgara/store/xa src/jar/tuples/java/org/mulgara/store/tuples src/jar/tuples-hybrid/java/org/mulgara/store/xa src/jar/util/java/org/mulgara/util src/jar/util-xa/java/org/mulgara/store/xa src/war/server-http/java src/war/web-services/WEB-INF

pag at mulgara.org pag at mulgara.org
Fri Mar 28 22:55:53 UTC 2008


Author: pag
Date: 2008-03-28 15:55:51 -0700 (Fri, 28 Mar 2008)
New Revision: 723

Added:
   branches/mgr-61-sparql/docs/site-src/design/JTAInterface.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/
   branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu
   branches/mgr-61-sparql/lib/axis-1.4.jar
   branches/mgr-61-sparql/lib/axis-ant-1.4.jar
   branches/mgr-61-sparql/lib/carol-2.0.5.jar
   branches/mgr-61-sparql/lib/howl-logger-0.1.11.jar
   branches/mgr-61-sparql/lib/jaxrpc-1.4.jar
   branches/mgr-61-sparql/lib/jotm-2.0.10.jar
   branches/mgr-61-sparql/lib/jotm_jrmp_stubs-2.0.10.jar
   branches/mgr-61-sparql/lib/log4j-1.2.15.jar
   branches/mgr-61-sparql/lib/saaj-1.4.jar
   branches/mgr-61-sparql/lib/wsdl4j-1.5.1.jar
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/CommandExecutor.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SelectElement.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/ResourceManagerInstanceAdaptor.java
   branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java
   branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/BackupRestoreSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ApplyRulesOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BuildRulesOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ExternalTransactionUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransaction.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransactionFactory.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransaction.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransactionFactory.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionFactory.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/Handler.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResource.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResourceWrapperXAResource.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiURLConnection.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/XAResourceWrapperRemoteXAResource.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/Assoc1toNMap.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriber.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriberXML.java
Removed:
   branches/mgr-61-sparql/jxdata/iTQL/exclude_queries/
   branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt
   branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu
   branches/mgr-61-sparql/lib/axis-1.1.jar
   branches/mgr-61-sparql/lib/axis-ant-1.1.jar
   branches/mgr-61-sparql/lib/jaxrpc-1.1.jar
   branches/mgr-61-sparql/lib/jotm-1.5.3-patched.jar
   branches/mgr-61-sparql/lib/jotm_carol-1.5.3.jar
   branches/mgr-61-sparql/lib/jotm_iiop_stubs-1.5.3.jar
   branches/mgr-61-sparql/lib/log4j-1.2.8.jar
   branches/mgr-61-sparql/lib/saaj-1.1.jar
   branches/mgr-61-sparql/lib/wsdl4j-1.4.jar
Modified:
   branches/mgr-61-sparql/.classpath
   branches/mgr-61-sparql/LEGAL.txt
   branches/mgr-61-sparql/build.properties
   branches/mgr-61-sparql/build.sh
   branches/mgr-61-sparql/build.xml
   branches/mgr-61-sparql/common.properties
   branches/mgr-61-sparql/common.xml
   branches/mgr-61-sparql/jxdata/iTQL/backup_restore/backup1Result3.txt
   branches/mgr-61-sparql/jxdata/iTQL/backup_restore/result3.txt
   branches/mgr-61-sparql/jxdata/iTQL/backup_restore/test.jxu
   branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult3.txt
   branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult5.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/base64Binary/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/hexBinary/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/boolean/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/gDates/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult34.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult37.txt
   branches/mgr-61-sparql/jxdata/iTQL/data_types/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult10.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult11.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult12.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult8.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult9.txt
   branches/mgr-61-sparql/jxdata/iTQL/filesystem/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/drop1.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/queryResult8.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result2.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result3.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result5.txt
   branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result7.txt
   branches/mgr-61-sparql/jxdata/iTQL/insert/queryResult1.txt
   branches/mgr-61-sparql/jxdata/iTQL/node_types/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/prefix/result1.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-container-membership-superProperty/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-domain-and-range/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subClassOf/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subPropertyOf/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-subPropertyOf-semantics/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/rdfs/statement-entailment/configResult.txt
   branches/mgr-61-sparql/jxdata/iTQL/standard_queries/queryResult17.txt
   branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult6.txt
   branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult7.txt
   branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult8.txt
   branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult9.txt
   branches/mgr-61-sparql/lib/antlr.jar
   branches/mgr-61-sparql/src/jar/ant-task/java/org/mulgara/ant/task/rdf/RDFLoad.java
   branches/mgr-61-sparql/src/jar/client-jrdf/java/org/mulgara/client/jrdf/test/ClientGraphUnitTest.java
   branches/mgr-61-sparql/src/jar/config/build.xml
   branches/mgr-61-sparql/src/jar/content-mbox/java/org/mulgara/content/mbox/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/content-mp3/java/org/mulgara/content/mp3/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/Parser.java
   branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/writer/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/content-rio/java/org/mulgara/content/rio/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/demo-mp3/java/org/mulgara/demo/mp3/swing/Mp3Application.java
   branches/mgr-61-sparql/src/jar/descriptor/src/java/org/mulgara/descriptor/PIErrorHandler.java
   branches/mgr-61-sparql/src/jar/itql/build.xml
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/Collaborator.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/CollaboratorUnitTest.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/HelpPrinter.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBean.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBeanUnitTest.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlOptionParser.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlSession.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/SableCCInterpreter.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlSession.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/URIUtil.java
   branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java
   branches/mgr-61-sparql/src/jar/itql/sablecc/itql.grammar
   branches/mgr-61-sparql/src/jar/krule/build.xml
   branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/KruleLoader.java
   branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/QueryStruct.java
   branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/Rule.java
   branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/RuleStructure.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/Connection.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/DummyConnection.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/SessionConnection.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/parser/Interpreter.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AggregateFunction.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerImpl.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperations.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperationsUnitTest.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerUnitTest.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstantValue.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintHaving.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintImpl.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintIs.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintNotOccurs.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccurs.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursLessThan.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursMoreThan.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelPartition.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResource.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResourceUnitTest.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Query.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/QueryUnitTest.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SingleTransitiveConstraint.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/TransitiveConstraint.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/UnconstrainedAnswer.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Variable.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/WalkConstraint.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/AddAlias.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Backup.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Command.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/CreateGraph.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Deletion.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/DropGraph.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Help.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Insertion.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Load.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/LocalCommand.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/NullOp.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Quit.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Restore.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetTime.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetUser.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/rdf/LiteralImplUnitTest.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/Session.java
   branches/mgr-61-sparql/src/jar/rdql/build.xml
   branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlOptionParser.java
   branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlSession.java
   branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/ForeignBlankNode.java
   branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/NetworkDelegator.java
   branches/mgr-61-sparql/src/jar/resolver-filesystem/java/org/mulgara/resolver/filesystem/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/resolver-http/java/org/mulgara/resolver/http/HttpContentUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java
   branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java
   branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java
   branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java
   branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java
   branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/ResolverSession.java
   branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TripleSetWrapperStatements.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreDuplicateResolution.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreInverseResolution.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolution.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFile.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFileUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleWriteThread.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImpl.java
   branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImplUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver-test/java/org/mulgara/resolver/test/TestResolverUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver-view/java/org/mulgara/resolver/view/ViewResolverUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver-xsd/java/org/mulgara/resolver/xsd/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/resolver/build.xml
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/AdvDatabaseSessionUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BackupOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BasicDatabaseSessionUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BootstrapOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/CreateModelOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionListQueryUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionUnitTest.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/InternalResolver.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LocalJRDFDatabaseSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LoginOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModelExistsOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModifyModelOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransaction.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionManager.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/Operation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/OperationContext.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PersistentResolverSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PreallocateOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/QueryOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RemoveModelOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RestoreOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/SetModelOperation.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/StringPoolSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/TestResolverSession.java
   branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/XADatabaseSessionUnitTest.java
   branches/mgr-61-sparql/src/jar/rules/java/org/mulgara/rules/Rules.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPAnswer.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPServer.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPSession.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandProfile.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandRequestHandler.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryProfile.java
   branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryRequestHandler.java
   branches/mgr-61-sparql/src/jar/server-http/build.xml
   branches/mgr-61-sparql/src/jar/server-http/java/org/mulgara/server/http/HttpSessionFactory.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImpl.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImplUnitTest.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerWrapperRemoteAnswerSerialised.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/PagedRemoteAnswer.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteAnswer.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSession.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionFactoryImpl.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionWrapperSession.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiServer.java
   branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/SessionWrapperRemoteSession.java
   branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/AbstractServer.java
   branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/EmbeddedMulgaraOptionParser.java
   branches/mgr-61-sparql/src/jar/sparql-protocol/java/org/mulgara/sparql/protocol/StreamAnswerTest.java
   branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImpl.java
   branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImplTest.java
   branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImplTest.java
   branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImplTest.java
   branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolLoadTest.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPObject.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPStringComparator.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPTypedLiteral.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/StringPoolAbstractTest.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBinaryComparator.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseInsensitiveStringComparator.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseSensitiveStringComparator.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPObjectFactoryImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPStringImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPTypedLiteralRegistry.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPURIImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralImpl.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringFactory.java
   branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringImpl.java
   branches/mgr-61-sparql/src/jar/store-xa/java/org/mulgara/store/xa/SimpleXAResourceException.java
   branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/BlockCacheLine.java
   branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/CacheLine.java
   branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuples.java
   branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuplesTest.java
   branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/MemoryCacheLine.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/ConstrainedNegationTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DefaultRowComparator.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DenseLongMatrix.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DifferenceUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuplesUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/HavingPredicates.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/JoinTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LimitedTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LiteralTuplesUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OffsetTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjection.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjectionUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicate.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicateFactory.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicatePrototype.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictionTuples.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/TestTuplesUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnboundJoinUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnconstrainedTuplesUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppend.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppendUnitTest.java
   branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedProjection.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFileTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLNode.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AbstractBlockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/Block.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFileTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeList.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeListTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFileTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/LockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFileTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFile.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFileTest.java
   branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ObjectPool.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/IntFile.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/LongToStringMap.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/MappedIntFile.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ResultSetMetaDataImpl.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/StringToLongMap.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TempDir.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSet.java
   branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSetTest.java
   branches/mgr-61-sparql/src/war/server-http/java/HttpServer.java
   branches/mgr-61-sparql/src/war/web-services/WEB-INF/server-config.wsdd
   branches/mgr-61-sparql/webdocs.xml
Log:
Merged and resolved latest trunk: svn merge -r 589:722 http://mulgara.org/svn/mulgara/trunk

Modified: branches/mgr-61-sparql/.classpath
===================================================================
--- branches/mgr-61-sparql/.classpath	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/.classpath	2008-03-28 22:55:51 UTC (rev 723)
@@ -67,18 +67,18 @@
 	<classpathentry kind="lib" path="lib/xmlc-taskdef-2.2.jar"/>
 	<classpathentry kind="lib" path="lib/xmlc-all-runtime-2.2.jar"/>
 	<classpathentry kind="lib" path="lib/xercesImpl.jar"/>
-	<classpathentry kind="lib" path="lib/wsdl4j-1.4.jar"/>
+	<classpathentry kind="lib" path="lib/wsdl4j-1.5.1.jar"/>
 	<classpathentry kind="lib" path="lib/trove-1.0.2.jar"/>
 	<classpathentry kind="lib" path="lib/sofa-1.0-alpha.jar"/>
 	<classpathentry kind="lib" path="lib/sablecc-2.18.2.jar"/>
-	<classpathentry kind="lib" path="lib/saaj-1.1.jar"/>
+	<classpathentry kind="lib" path="lib/saaj-1.4.jar"/>
 	<classpathentry kind="lib" path="lib/Quick4util.jar"/>
 	<classpathentry kind="lib" path="lib/Quick4rt.jar"/>
 	<classpathentry kind="lib" path="lib/plankton-1.2.6.jar"/>
 	<classpathentry kind="lib" path="lib/org.mortbay.jetty-4.2.19.jar"/>
 	<classpathentry kind="lib" path="lib/org.mortbay.jetty.plus-4.2.19.jar"/>
 	<classpathentry kind="lib" path="lib/mail-1.3.jar"/>
-	<classpathentry kind="lib" path="lib/log4j-1.2.8.jar"/>
+	<classpathentry kind="lib" path="lib/log4j-1.2.15.jar"/>
 	<classpathentry kind="lib" path="lib/jxunit3.jar"/>
 	<classpathentry kind="lib" path="lib/junit-3.8.1.jar"/>
 	<classpathentry kind="lib" path="lib/jtidy-r7-xmlc-2.2.jar"/>
@@ -86,13 +86,14 @@
 	<classpathentry kind="lib" path="lib/jsr173_07_ri.jar"/>
 	<classpathentry kind="lib" path="lib/jsr173_07_api.jar"/>
 	<classpathentry kind="lib" path="lib/js-1.5r3.jar"/>
-	<classpathentry kind="lib" path="lib/jotm-1.5.3-patched.jar"/>
-	<classpathentry kind="lib" path="lib/jotm_iiop_stubs-1.5.3.jar"/>
-	<classpathentry kind="lib" path="lib/jotm_carol-1.5.3.jar"/>
+	<classpathentry kind="lib" path="lib/jotm-2.0.10.jar"/>
+	<classpathentry kind="lib" path="lib/jotm_jrmp_stubs-2.0.10.jar"/>
+	<classpathentry kind="lib" path="lib/carol-2.0.5.jar"/>
+	<classpathentry kind="lib" path="lib/howl-logger-0.1.11.jar"/>
 	<classpathentry kind="lib" path="lib/jl1.0.jar"/>
 	<classpathentry kind="lib" path="lib/jid3-0.34.jar"/>
 	<classpathentry kind="lib" path="lib/jboss-j2ee.jar"/>
-	<classpathentry kind="lib" path="lib/jaxrpc-1.1.jar"/>
+	<classpathentry kind="lib" path="lib/jaxrpc-1.4.jar"/>
 	<classpathentry kind="lib" path="lib/javax.servlet-2.3.jar"/>
 	<classpathentry kind="lib" path="lib/javacc.jar"/>
 	<classpathentry kind="lib" path="lib/jasper-runtime-4.2.29.jar"/>
@@ -112,8 +113,8 @@
 	<classpathentry kind="lib" path="lib/beepcore-0.9.08.jar"/>
 	<classpathentry kind="lib" path="lib/barracuda-ant-1.2.6.jar"/>
 	<classpathentry kind="lib" path="lib/barracuda-1.2.6.jar"/>
-	<classpathentry kind="lib" path="lib/axis-ant-1.1.jar"/>
-	<classpathentry kind="lib" path="lib/axis-1.1.jar"/>
+	<classpathentry kind="lib" path="lib/axis-ant-1.4.jar"/>
+	<classpathentry kind="lib" path="lib/axis-1.4.jar"/>
 	<classpathentry kind="lib" path="lib/aspectjrt-1.2.jar"/>
 	<classpathentry kind="lib" path="lib/apache-soap-2.2.jar"/>
 	<classpathentry kind="lib" path="lib/antlr.jar"/>

Modified: branches/mgr-61-sparql/LEGAL.txt
===================================================================
--- branches/mgr-61-sparql/LEGAL.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/LEGAL.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -59,10 +59,10 @@
               http://www.eclipse.org/legal/cpl-v10.html
 
     AXIS
-    JARs:     axis-1.1.jar
-              axis-ant-1.1.jar
-              saaj-1.1
-              jaxrpc-1.1.jar
+    JARs:     axis-1.4.jar
+              axis-ant-1.4.jar
+              saaj-1.4
+              jaxrpc-1.4.jar
     URL:      http://ws.apache.org/axis/index.html
     LICENSE:  Apache Software License, v2.0
               http://www.apache.org/licenses/LICENSE-2.0
@@ -202,15 +202,36 @@
               http://www.gnu.org/copyleft/lesser.html
     
     JOTM (Java Open Transaction Manager)
-    JARs:     jotm-1.5.3.jar (locally patched)
-              jotm_carol-1.5.3.jar
-              jotm_iiop_stubs-1.5.3.jar
-              connector-1_5.jar (J2EE spec from Sun)
-              jta-spec1_0_1.jar (J2EE spec from Sun)
+    JARs:     jotm-2.0.10.jar
+              jotm_jrmp_stubs-2.0.10.jar
     URL:      http://jotm.objectweb.org/ 
     LICENSE:  BSD-style
               http://jotm.objectweb.org/bsd_license.html
+    
+    CAROL (Common Architecture for RMI ObjectWeb Layer)
+    JARs:     carol-2.0.5.jar
+    URL:      http://carol.objectweb.org/ 
+    LICENSE:  LGPL
+              http://www.gnu.org/copyleft/lesser.html
 
+    HOWL (High-speed ObjectWeb Logger)
+    JARs:     howl-logger-0.1.11.jar
+    URL:      http://howl.objectweb.org/ 
+    LICENSE:  Bull S.A.
+              http://howl.objectweb.org/license.html
+
+    Java Transaction API
+    JARs:     jta-spec1_0_1.jar
+    URL:      http://java.sun.com/products/jta
+    License:  Common Development and Distribution License (CDDL) v1.0
+              http://www.sun.com/cddl/cddl.html
+
+    JavaEE Connector Architecture (JCA)
+    JARs:     connector-1_5.jar (J2EE spec from Sun)
+    URL:      http://java.sun.com/j2ee/connector/
+    License:  Common Development and Distribution License (CDDL) v1.0
+              http://www.sun.com/cddl/cddl.html
+
     JRDF
     JARs:     jrdf-0.3.4.3.jar
     URL:      http://mulgara.org/files/jrdf/
@@ -232,7 +253,7 @@
               http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/jtidy/jtidy/LICENSE.
     
     Log4J
-    JARs:     log4j-1.2.8.jar
+    JARs:     log4j-1.2.15.jar
     URL:      http://jakarta.apache.org
     LICENSE:  Apache Software License, v2.0
               http://www.apache.org/licenses/LICENSE-2.0
@@ -268,7 +289,7 @@
               http://www.opensource.org/licenses/lgpl-license.php
     
     WSDL4J
-    JARs:     wsdl4j-1.4.jar
+    JARs:     wsdl4j-1.5.1.jar
     URL:      http://sourceforge.net/projects/wsdl4j
     LICENSE:  Common Public License
               http://oss.software.ibm.com/developerworks/opensource/CPLv1.0.htm

Modified: branches/mgr-61-sparql/build.properties
===================================================================
--- branches/mgr-61-sparql/build.properties	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/build.properties	2008-03-28 22:55:51 UTC (rev 723)
@@ -97,7 +97,7 @@
 antlr.jar                =antlr.jar
 apache.soap.jar          =apache-soap-2.2.jar
 aspectjrt.jar            =aspectjrt-1.2.jar
-axis.jar                 =axis-1.1.jar
+axis.jar                 =axis-1.4.jar
 barracuda.jar            =barracuda-1.2.6.jar
 beep.jar                 =beepcore-0.9.08.jar
 bsh.jar                  =bsh-2.0b1.jar
@@ -115,7 +115,7 @@
 jargs.jar                =jargs-0.2.jar
 jasper.compiler.jar      =jasper-compiler-4.2.29.jar
 jasper.runtime.jar       =jasper-runtime-4.2.29.jar
-jaxrpc.jar               =jaxrpc-1.1.jar
+jaxrpc.jar               =jaxrpc-1.4.jar
 jakarta-oro.jar          =jakarta-oro-2.0.5.jar
 jca.jar                  =connector-1_5.jar
 jena.jar                 =jena-2.1.jar
@@ -129,21 +129,22 @@
 jsr.173.api.jar          =jsr173_07_api.jar
 jsr.173.ri.jar           =jsr173_07_ri.jar
 jta.jar                  =jta-spec1_0_1.jar
-jotm.carol.jar           =jotm_carol-1.5.3.jar
-jotm.iiop.jar            =jotm_iiop_stubs-1.5.3.jar
-jotm.jar                 =jotm-1.5.3-patched.jar
+carol.jar                =carol-2.0.5.jar
+jotm.jrmp.jar            =jotm_jrmp_stubs-2.0.10.jar
+jotm.jar                 =jotm-2.0.10.jar
+howl.jar                 =howl-logger-0.1.11.jar
 l2fprod-common-sheet.jar =l2fprod-common-sheet.jar
-log4j.jar                =log4j-1.2.8.jar
+log4j.jar                =log4j-1.2.15.jar
 lucene.jar               =lucene-2.0.0.jar
 mail.jar                 =mail-1.3.jar
-saaj.jar                 =saaj-1.1.jar
+saaj.jar                 =saaj-1.4.jar
 servlet.jar              =javax.servlet-2.3.jar
 simple-jndi.jar          =simple-jndi-0.9.jar
 sofa-doc.jar             =sofa-doc.jar
 sofa.jar                 =sofa-1.0-alpha.jar
 swoop.jar                =swoop-modified-${tks-version}.jar
 trove.jar                =trove-1.0.2.jar
-wsdl4j.jar               =wsdl4j-1.4.jar
+wsdl4j.jar               =wsdl4j-1.5.1.jar
 xerces.jar               =xercesImpl.jar
 xmlParserAPIs.jar        =xmlParserAPIs.jar
 xom.jar                  =xom-1.0d21.jar

Modified: branches/mgr-61-sparql/build.sh
===================================================================
--- branches/mgr-61-sparql/build.sh	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/build.sh	2008-03-28 22:55:51 UTC (rev 723)
@@ -116,7 +116,7 @@
 fi
 
 # Call Ant
-${JAVABIN} ${ARCH} -Xms64m -Xmx192m -Dant.home=${ANT_HOME} -DJAVAC=${JAVAC} \
+${JAVABIN} ${ARCH} -Xms64m -Xmx256m -Dant.home=${ANT_HOME} -DJAVAC=${JAVAC} \
            -Darch.bits=${ARCH} \
            -Ddir.base=${BASEDIR} \
            -classpath "${CLASSPATH}" org.apache.tools.ant.Main \

Modified: branches/mgr-61-sparql/build.xml
===================================================================
--- branches/mgr-61-sparql/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -175,7 +175,7 @@
        <pathelement path="${dist.dir}/${driver.jar}"/>
        <pathelement path="${dist.dir}/${ant-task.jar}"/>
        <pathelement path="${lib.dir}/apache-soap-2.2.jar"/>
-       <pathelement path="${lib.dir}/log4j-1.2.8.jar"/>
+       <pathelement path="${lib.dir}/log4j-1.2.15.jar"/>
      </classpath>
     </taskdef>
 
@@ -193,7 +193,7 @@
        <pathelement path="${dist.dir}/${driver.jar}"/>
        <pathelement path="${dist.dir}/${ant-task.jar}"/>
        <pathelement path="${lib.dir}/apache-soap-2.2.jar"/>
-       <pathelement path="${lib.dir}/log4j-1.2.8.jar"/>
+       <pathelement path="${lib.dir}/log4j-1.2.15.jar"/>
      </classpath>
     </taskdef>
 
@@ -217,6 +217,8 @@
     <delete dir="${javadoc.dir}"/>
     <delete dir="${jxtest.dir}"/>
     <delete dir="${src.docs.dir}"/>
+    <delete dir="${basedir}/testDatabase"/>
+    <delete dir="${basedir}/sqltest"/>
     <delete>
       <fileset dir="${basedir}" includes="*.log*"/>
     </delete>
@@ -489,10 +491,10 @@
           lib/${resolver-distributed.jar},
           lib/${resolver-jar.jar}, lib/${dtd.jar}, lib/${jrdf.base.jar}
           lib/activation-1.0.2.jar, lib/icu4j.jar, lib/jena-2.1.jar, lib/antlr.jar,
-          lib/${date-utils.jar}, lib/${commons-logging.jar}, lib/beepcore-0.9.08.jar, lib/log4j-1.2.8.jar, lib/${lucene.jar}, lib/mail-1.3.jar,
+          lib/${date-utils.jar}, lib/${commons-logging.jar}, lib/beepcore-0.9.08.jar, lib/log4j-1.2.15.jar, lib/${lucene.jar}, lib/mail-1.3.jar,
           lib/${jetty.jar}, lib/${jetty.plus.jar}, lib/${jasper.compiler.jar}, lib/${servlet.jar}, lib/jargs-0.2.jar,
           lib/castor-0.9.3.9-xml.jar, lib/trove-1.0.2.jar, lib/${jrdf.jar}, lib/${saaj.jar},
-          lib/${jakarta-oro.jar}, lib/jta-spec1_0_1.jar, lib/${jotm.jar}, lib/${jotm.carol.jar}, lib/${jotm.iiop.jar},
+          lib/${jakarta-oro.jar}, lib/jta-spec1_0_1.jar, lib/${jotm.jar}, lib/${jotm.jrmp.jar}, lib/${carol.jar}, lib/${howl.jar},
           lib/connector-1_5.jar, lib/${httpclient.jar}, lib/${commons-codec.jar}"/>
       <attribute name="Embedded-Main-Class" value="org.mulgara.server.EmbeddedMulgaraServer"/>
     </manifest>
@@ -548,7 +550,7 @@
         ${lucene.jar}, ${mail.jar}, ${castor.jar}, ${trove.jar},
         ${date-utils.jar}, ${commons-logging.jar}, ${commons-httpclient.jar},
         ${commons-codec.jar}, ${emory-util.jar},
-        ${jotm.jar}, ${jotm.carol.jar}, ${jotm.iiop.jar}, ${jta.jar},
+        ${jotm.jar}, ${jotm.jrmp.jar}, ${carol.jar}, ${howl.jar}, ${jta.jar},
         ${jsr.173.api.jar}, ${jsr.173.ri.jar}, ${jca.jar}, ${saaj.jar},
         ${axis.jar}, ${commons-discovery.jar}, ${jaxrpc.jar}, ${wsdl4j.jar},
         ${jena.jar}, ${antlr.jar}, ${jakarta-oro.jar}, {jid3.jar}"/>
@@ -998,7 +1000,7 @@
 
       <sysproperty key="java.io.tmpdir" value="${tmp.dir}"/>
       <sysproperty key="log4j.configuration"
-                   value="${baseuri}/conf/log4j-itql.xml"/>
+                   value="${baseuri}/conf/log4j-tql.xml"/>
 
       <classpath>
 
@@ -1674,28 +1676,9 @@
        <param name="output.dir" expression="${test.dir}"/>
     </xslt>
 
-    <script language="javascript">
-      <![CDATA[
-      try {
-        // read the first line of the version file
-        var summaryFile = project.getProperty("test.dir") + "/junit-summary.txt";
-        var bufferedReader =
-               new java.io.BufferedReader(new java.io.FileReader(summaryFile));
-
-        var line = bufferedReader.readLine();
-        while ( line != null ) {
-           java.lang.System.out.println( line );
-           line = bufferedReader.readLine();
-        }
-        bufferedReader.close();
-
-      } catch (ex) {
-        java.lang.System.out.println("Unable to JUnit summary file "+ ex.getMessage());
-      }
-
-      ]]>
-    </script>
-
+    <concat>
+      <fileset file="${test.dir}/junit-summary.txt"/>
+    </concat>
   </target>
 
   <!-- =================================================================== -->
@@ -1764,8 +1747,9 @@
       <zipfileset src="${lib.dir}/${commons-codec.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${emory-util.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jotm.jar}" excludes="META-INF/**"/>
-      <zipfileset src="${lib.dir}/${jotm.carol.jar}" excludes="META-INF/**"/>
-      <zipfileset src="${lib.dir}/${jotm.iiop.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${jotm.jrmp.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${carol.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${howl.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jta.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jsr.173.api.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jsr.173.ri.jar}" excludes="META-INF/**"/>
@@ -1903,6 +1887,15 @@
           depends="dist, client-test, session-test, resolver-api-test, store-xa-test,
                    utils-test, jxtest, store-stringpool-xa-loadtest, publish-summary"
           description="Runs all tests (updates source first)">
+
+    <loadfile property="test.status.success" srcfile="${test.dir}/junit-summary.txt">
+      <filterchain>
+        <linecontainsregexp>
+          <regexp pattern="Success rate *100\.?0?0?%"/>
+        </linecontainsregexp>
+      </filterchain>
+    </loadfile>
+    <fail unless="test.status.success"/>
   </target>
 
   <target name="client-test"

Modified: branches/mgr-61-sparql/common.properties
===================================================================
--- branches/mgr-61-sparql/common.properties	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/common.properties	2008-03-28 22:55:51 UTC (rev 723)
@@ -51,5 +51,7 @@
 arch.bits=-Dnoop
 
 # VM argument for component test
-jvm.args=-Xmx512M
+jvm.args=-Xmx640M
 
+# test server arguments; can be set with -Dtest.server.args=... on the command line
+test.server.args=

Modified: branches/mgr-61-sparql/common.xml
===================================================================
--- branches/mgr-61-sparql/common.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/common.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -61,14 +61,14 @@
 
       <classpath>
 
-        <fileset dir="${lib.dir}" includes="**/axis-1.1.jar"/>
-        <fileset dir="${lib.dir}" includes="**/axis-ant-1.1.jar"/>
-        <fileset dir="${lib.dir}" includes="**/wsdl4j-1.4.jar"/>
-        <fileset dir="${lib.dir}" includes="**/log4j-1.2.8.jar"/>
+        <fileset dir="${lib.dir}" includes="**/axis-1.4.jar"/>
+        <fileset dir="${lib.dir}" includes="**/axis-ant-1.4.jar"/>
+        <fileset dir="${lib.dir}" includes="**/wsdl4j-1.5.1.jar"/>
+        <fileset dir="${lib.dir}" includes="**/log4j-1.2.15.jar"/>
         <fileset dir="${lib.dir}" includes="**/commons-logging-1.0.3.jar"/>
         <fileset dir="${lib.dir}" includes="**/commons-discovery-1.2.jar"/>
-        <fileset dir="${lib.dir}" includes="**/jaxrpc-1.1.jar"/>
-        <fileset dir="${lib.dir}" includes="**/saaj-1.1.jar"/>
+        <fileset dir="${lib.dir}" includes="**/jaxrpc-1.4.jar"/>
+        <fileset dir="${lib.dir}" includes="**/saaj-1.4.jar"/>
       </classpath>
     </taskdef>
   </target>
@@ -151,8 +151,8 @@
                        jargs-*.jar, org.mortbay.jetty*.jar, jta-spec*.jar,
                        jotm*.jar, commons-logging-*.jar, Quick4rt.jar,
                        commons-discovery-*.jar, commons-httpclient-*.jar,
-                       commons-codec-*.jar, connector-*.jar,
-                       ${date-utils.jar}"
+                       commons-codec-*.jar, connector-*.jar, jaxrpc-*.jar,
+                       carol*.jar, howl-logger*.jar, ${date-utils.jar}"
              excludes="jboss-j2ee.jar"/>
   </path>
 
@@ -280,12 +280,76 @@
       <batchtest todir="${junit.results.tmpdir}">
         <fileset dir="${dir}/java" includes="**/*Test.java"
                  excludes="**/*AbstractTest.java, **/*LoadTest.java,
-                           **/*StressTest.java"/>
+                           **/*StressTest.java, **/*StandaloneTest.java"/>
       </batchtest>
     </junit>
   </target>
 
   <!-- =================================================================== -->
+  <!-- Run JUnit regression tests requiring a standalone instance          -->
+  <!--                                                                     -->
+  <!-- Required parameters: $classpath.id, $dir, $jar                      -->
+  <!-- =================================================================== -->
+  <target name="standalone-test"
+          depends="uri, dtd-jar, host.name, dist"
+          description="run regression tests requiring a standalone instance">
+
+    <copy file="${conf.dir}/log4j-template.xml"
+          tofile="${basedir}/log4j-conf.xml"/>
+
+    <mkdir dir="${junit.results.tmpdir}"/>
+
+    <!-- stop and start the server -->
+    <ant target="stop"/>
+    <ant target="start"/>
+
+    <junit fork="yes" haltonfailure="no" printsummary="on"
+           jvm="${java.home}/bin/java" dir="${basedir}">
+
+      <jvmarg value="${arch.bits}"/>
+      <jvmarg value="-ea"/>
+      <jvmarg value="${jvm.args}"/>
+
+      <sysproperty key="java.io.tmpdir" value="${tmp.dir}"/>
+      <sysproperty key="test.dir" value="${test.dir}"/>
+      <sysproperty key="admin" value=""/>
+      <sysproperty key="itql.command.log" value="${tmp.dir}/itql.log"/>
+      <sysproperty key="org.mulgara.xml.ResourceDocumentBuilderFactory"
+                   value="org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"/>
+      <sysproperty key="java.naming.factory.initial"
+                   value="com.sun.jndi.rmi.registry.RegistryContextFactory"/>
+      <sysproperty key="java.naming.provider.url" value="rmi://localhost"/>
+      <sysproperty key="java.rmi.server.codebase"
+                   value="${bin.uri}/${rmi.base.jar}"/>
+      <sysproperty key="java.security.manager" value=""/>
+      <sysproperty key="java.security.policy"
+                   value="${basedir}/conf/mulgara-test.policy"/>
+      <sysproperty key="host.name" value="${host.name}"/>
+
+      <!-- The cvs.root property allows tests to find CVS'ed test data -->
+      <sysproperty key="cvs.root" value="${basedir}"/>
+      <sysproperty key="mulgara.jar" value="${mulgara.jar}"/>
+      <sysproperty key="log4j.configuration" value="${baseuri}/log4j-conf.xml"/>
+      <sysproperty key="basedir" value="${basedir}"/>
+      <sysproperty key="org.mulgara.test" value="${org.mulgara.test}"/>
+
+      <classpath>
+        <fileset dir="${dist.dir}" includes="${mulgara.jar}"/>
+      </classpath>
+
+      <formatter type="xml"/>
+
+      <batchtest todir="${junit.results.tmpdir}">
+        <fileset dir="${dir}/java" includes="**/*StandaloneTest.java"/>
+      </batchtest>
+    </junit>
+
+    <!-- stop the server -->
+    <ant target="stop"/>
+
+  </target>
+
+  <!-- =================================================================== -->
   <!-- Run JUnit load tests on a JAR component                             -->
   <!--                                                                     -->
   <!-- Required parameters: $classpath.id, $dir, $jar                      -->
@@ -530,6 +594,7 @@
 
       <arg value="-a"/>
       <arg value="${test.dir}"/>
+      <arg line="${test.server.args}"/>
     </exec>
 
     <exec os="SunOS" executable="${scripts.dir}/bg.sh" failonerror="yes">
@@ -547,6 +612,7 @@
       <arg value="${dist.dir}/${mulgara.jar}"/> -->
       <arg value="-a"/>
       <arg value="${test.dir}"/>
+      <arg line="${test.server.args}"/>
     </exec>
 
     <exec os="Mac OS X" executable="${scripts.dir}/bg.sh" failonerror="yes">
@@ -563,6 +629,7 @@
       <arg value="${dist.dir}/${mulgara.jar}"/> -->
       <arg value="-a"/>
       <arg value="${test.dir}"/>
+      <arg line="${test.server.args}"/>
     </exec>
 
     <exec os="Windows NT,Windows 2000,Windows XP, Windows 2003"
@@ -580,6 +647,7 @@
       <arg value="${dist.dir}\${mulgara.jar}"/> -->
       <arg value="-a"/>
       <arg value="${test.dir}"/>
+      <arg line="${test.server.args}"/>
     </exec>
 
     <!-- wait for the server to start -->
@@ -615,34 +683,15 @@
     <echo>Waiting for server to start on shutdown hook
           ${shutdownhook.port}</echo>
 
-    <script language="javascript">
+    <waitfor maxwait="120000" checkevery="1000" timeoutproperty="start.failed">
+      <socket server="localhost" port="${shutdownhook.port}"/>
+    </waitfor>
+    <sleep seconds="5"/>
 
-      <![CDATA[
-
-      var socket;
-      for (i=5; i<=120; i+=5) {
-        java.lang.Thread.sleep(5000);
-        try {
-          // Create a connection to the shut-down port.
-          socket = java.net.Socket("localhost",
-            project.getProperty("shutdownhook.port"));
-          socket.close();
-          break;
-        }
-        catch (ex) {
-         java.lang.System.out.println(ex+" after "+i+" seconds");
-        }
-      }
-      if (socket) {
-        java.lang.System.out.println("Mulgara started");
-        java.lang.Thread.sleep(5000);
-      }
-      else {
-        java.lang.System.out.println("Mulgara not started");
-      }
-
-      ]]>
-    </script>
+    <condition property="msg" value="Mulgara not started" else="Mulgara started">
+      <isset property="start.failed"/>
+    </condition>
+    <echo>${msg}</echo>
   </target>
 
   <!-- =================================================================== -->

Copied: branches/mgr-61-sparql/docs/site-src/design/JTAInterface.txt (from rev 722, trunk/docs/site-src/design/JTAInterface.txt)
===================================================================
--- branches/mgr-61-sparql/docs/site-src/design/JTAInterface.txt	                        (rev 0)
+++ branches/mgr-61-sparql/docs/site-src/design/JTAInterface.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,271 @@
+The Mulgara JTA Interface
+
+The Existing Interface
+
+Mulgara originally provided two transactional interfaces, implicit and explicit.
+This mediated via the Session object, and the method used to select between them
+is called setAutoCommit().  When auto-commit is true, all operations on the
+Session use the implicit interface.  Setting auto-commit false initiates an
+explicit (or user-demarcated) transaction.  Irrespective of any commit/rollback,
+once auto-commit is false all transactions are user-demarcated until it is set
+to true again.  While auto-commit is true every operation on the Session will
+initiate a new transaction which will be finalised (either commit or rollback)
+before the operation returns.
+
+All transactions initiated via the explicit interface are read-write, whereas
+only those operations that perform updates initiate implicit read-write
+transactions.  Naturally both interfaces use the same underlying transactional
+mechanisms within Mulgara, including a single shared write-lock that only
+permits a single read-write transaction to proceed at a time.
+
+Explicit transactions are controlled via three methods on the Session interface.
+ - Session::setAutoCommit() allows the developer to select which transactional
+   interface to use, and to initiate a transaction (this does conflate two
+   concepts, but todate that has not proven to be a problem).
+ - Session::commit() commits the current transaction an initiates a new
+   transaction without dropping the write-lock.
+ - Session::rollback() rollbacks the current transaction an initiates a new
+   transaction without dropping the write-lock.
+There are two other ways for a user-demarcated transaction to be terminated.
+ - If an exception is thrown from an operation on the session, or on a query
+   result associated with the transaction, the transaction is rolled back and
+   the write-lock is dropped.
+ - If the transaction timeout expires then the transaction is rolled back and
+   the write-lock is dropped.
+In both cases the session remains in explicit transaction control however as
+all operations start by attempting to activate the transaction, any attempt to
+perform any non-transaction control operation on the session results in an
+exception.
+
+To ensure full transaction isolation/serialisability each answer returned from a
+query holds a reference to the transaction/phase it was performed against.  This
+means that the results of queries performed within an implicit transaction
+remain valid until such a time as either the result or the originating session
+itself is closed.  However due to this reliance on the originating transaction,
+query results obtained from an explicit transaction do not out live it, and are
+invalidated as soon as the transaction is terminated.
+
+This approach greatly simplifies the normal case of an application that is
+performing an atomic insert, delete, or query.  In this case the application
+developer can ignore transactions altogether and the implict transaction control
+will 'do the right thing'.  For more complex applications, the explicit
+transation controls available on session are sufficient for almost all uses of
+mulgara as a standalone store.
+
+Motivation for a new interface
+
+There are however two gaps in the original transaction interface.
+
+The first is that it is impossible to perform a series of transactionally
+consistant queries except by grouping them into a single call to
+Session::query(List); or by first initiating an explicit transaction in order to
+obtain the write-lock, preventing any potentially inconsistent updates.
+Naturally the former is not always possible, and the latter is undesirable,
+especially as mulgara is a multiversion datastore and it therefore should be
+possible to obtain a handle to a given version (phase) and run multiple queries
+against it.
+
+The second is that the interface provides no access to the two-phase commit
+protocol used by mulgara internally.  This isn't a problem when using mulgara as
+a standalone server, however it does make it impossible to incorporate mulgara
+in a distributed transaction with other stores or databases safely.
+
+The Java standard for providing access to a two-phase commit protocol is the
+"Java Transaction API" (JTA).  A java transaction (and slight simplification) of
+the Object Management Group (OMG)'s "Transaction Service Specification" (OTS), which
+is the transaction management specification for CORBA.  The OTS is itself an
+object-oriented mapping of the "DTP/XA Specification" (XA-spec)from X/Open (now The Open
+Group).  The relevant versions of the various specifications are:
+  - JTA : Java Transaction API (JTA), Version 1.1, 2002
+  - OTS : Transaction Service Specification, Version 1.2, 2001
+  - XA-Spec : Distributed Transaction Processing: The XA Specification,
+    XO/CAE/91/300, 1991
+The XA-Spec relies for context on the "DTP/Reference Model" (XA-model), 1991;
+although the mulgara JTA implementation was guided with reference to the more
+recent version 3, 1996.
+  - XA-model : Distribute Transaction Processing: Reference Model Version 3,
+    G504, 1996
+
+While the primary requirement for JTA support is the need to provide a two-phase
+commit interface, the opportunity was also taken to provide explicit control of
+read-only transactions which solves the problem of supporting multiple
+consistent reads as discussed above.
+
+Limitations of the JTA interface
+
+The write-lock is not a consequence of the existing interface, but rather a
+property of the underlying mulgara XA1 store implementation.  As a result the
+use of JTA does not affect the serialisation of write transactions.  It remains
+the case that any attempt to initiate a write-transaction will block until such
+a time as the write-lock becomes available.  The current JTA implementation
+within mulgara does not provide any timeout on this wait, so application
+developers should be aware that calls to start a mulgara transaction may block
+for an arbitary time.  
+
+On restart mulgara automatically and releases (garbage collects) any phases
+(versions) other than the most recently committed.  This startup protocol is
+done without any journal reruns resulting in an instantaneous restart.  On the
+other hand this protocol does mean that mulgara discards any prepared
+transactions on restart, effectively performing a heuristic rollback.  As
+mulgara makes no distinction between prepared and unprepared transactions on
+restart, mulgara does not persist the prepared status of a transaction.  This
+means that the mulgara JTA implementation cannot participate in the JTA recovery
+protocol.  As a result on restart users should consider all transactions to be
+Heuristically Completed (state S5 in XA-spec 6.3), with status XA_HEURRB in the
+case of a restart prior to a call to commit, and status XA_HEURHAZ on a restart
+during a commit call.  It is apropos here to recall that XA_HEURMIX is only
+possible if an update operation is performed on an external datastore via a
+resolver (at the moment only lucene supports this); atomicity is guaranteed
+with respect to the mulgara rdf-store itself.
+
+The JTA interface is a Java interface that is expected to operate transparently
+over a network.  As with Mulgara's session interface, the JTA interface uses RMI
+to provide network transparency.  This should not be a problem as the RMI based
+JTA implementation can only be obtained via the RMI based session
+implementation, however any interruption to RMI operation will affect 
+transaction control.
+
+Accessing the JTA interface
+
+The fundamental requirement for supporting JTA is providing a way of obtaining
+an XAResource.  JTA requires that each XAResource be associated with a "Resource
+Manager Instance".  When mapping this to Mulgara, and taking into consideration
+the code in the JTA-spec (3.4.9), the Session object was identified as best
+fitting JTA's use of the term RM instance.  The JTA interface therefore adds two
+new methods to Session:
+  Session::getXAResource()
+  Session::getReadOnlyXAResource()
+Both return an XAResource object, associated with the session.  All transactions
+initiated via a call to XAResource::start() will be read-write or read-only
+depending on if the XAResource was obtained via getXAResource or
+getReadOnlyXAResource respectively.
+
+The preexisting interface manages the transaction state transitions internally,
+as compared to the JTA interface which exposes these transitions to the external
+control of an external transaction manager.  Consequently within mulgara
+transactions created via the JTA interface are referred to as "external
+transactions", those by the older implicit and explicit interface as "internal
+transactions".  While JTA 3.4.7 encourages supporting both Local (internal) and
+Global (external) transactions through the same "connection", supporting this
+would drastically increase the number of operation combinations that would need
+to be tested to ensure confidence in the transaction logic.  Therefore the
+current mulgara JTA implementation does not support the use of both internal and
+external transactions on the same session.  To select which interface is active
+on a given session the developer should simply use it.  The first use of a given
+interface (internal or external) disables the other.  This ensures full
+backwards compatibility with existing code while simplifying the process of
+testing and building confidence in the new interface.
+
+Using the JTA interface
+
+It is worth mentioning that none of the underlying transactional machinery has
+changed, consequently all Answer objects still reference their originating
+transaction, and all transactions ultimately must map to a specific phase on the
+store.  As a result it is important to keep in mind that once a JTA mediated
+transaction is terminated via the XAResource, the reference to the phase is
+released and all outstanding Answer objects are invalidated.  In this the JTA
+interface works very similarly to the explict internal interface.
+
+JTA also recommends supporting multiple outstanding transactions on a single RM
+instance.  The mulgara JTA implementation provides full support for this,
+however developers attempting to use this functionality *must* be careful to
+observe the restrictions imposed by the JTA standard.  JTA provides support for
+concurrent transactions on a single resource adaptor via calls to
+XAResource::suspend() and XAResource::resume().  These transition the specified
+transaction from Associated to Suspended states (see JTA-spec 3.4.4, although
+XA-spec Ch.6 is more complete).  JTA requires (as does the mulgara
+implementation) that at most one transaction be associated with the
+transactional resource at any given time.
+
+The following example of concurrent use of JTA transactions on a single session
+is excerpted from org.mulgara.resolver.JotmTransactionStandaloneUnitTest.java
+
+{
+  txManager.begin();
+
+  Session session = sessionFactory.newSession();
+  XAResource roResource = session.getReadOnlyXAResource();
+  XAResource rwResource = session.getXAResource();
+
+  /*
+   * Note: JTA requires that you initiate the global transaction (via mgr::begin()
+   * above), before you enlist a resource.
+   * The call to enlistResource for an XAResource for the first time in a given
+   * global transaction will cause the Transaction Manager to call xa::start() on
+   * the XAResource, initiating a mulgara transaction.
+   * As we are using an XAResource obtained via xa::getXAResource(), this
+   * transaction will be a read-write transaction - note this does mean that
+   * this call could block waiting on the write-lock availability.
+   */
+  txManager.getTransaction().enlistResource(rwResource);
+  session.createModel(...);
+  Transaction tx1 = txManager.suspend();
+  /*
+   * Note: Without the call to mgr::suspend, subsequent calls to enlistResource will
+   * detect that there is an existing transaction and result in a call to
+   * xa::start(TM_JOIN), which is either a no-op (if a read-only 'joins' a
+   * read-write transaction) or an exception (if a read-write attempts to 'join'
+   * a read-only transaction).
+   * With the call to mgr::suspend() the transaction is temporarally
+   * disassociated from this thread, and from this session.  A Consequent call to
+   * mgr::begin() will result in the transaction manager initiating a new
+   * transaction, and an ensuing call to xa::enlistResource a new mulgara
+   * transaction.
+   * It is important to realise that all operations on a session object are
+   * evaluated with respect to the currently associated transaction.  If all
+   * transactions are suspended or completed then operations will result in an
+   * exception.
+   */
+
+  txManager.begin();
+  txManager.getTransaction().enlistResource(roResource);
+  Answer answer = session.query(new Query(...));
+  Transaction tx2 = txManager.suspend();
+
+  /*
+   * Answers carry their own association with the mulgara transaction, so the
+   * transaction does not need to be reassociated with the originating session
+   * to use an Answer object.  This does run counter to assumptions of the JTA
+   * specification, however as the JTA specification assumes a traditional
+   * relational database, many of the capabilities of multiversion datastores
+   * (such as mulgara) flexibility is required in adapting multiversion
+   * transactions to JTA.
+   */
+  answer.beforeFirst();
+  while (answer.next()) {
+    ...
+  }
+
+  txManager.resume(tx1);
+  session.insert(...);
+  tx1 = txManager.suspend();
+  answer.close();
+  txManager.resume(tx1);
+  txManager.commit();
+
+  /*
+   * Note the suport for user-demarcated concurrent read-only transactions.
+   */
+  txManager.begin();
+  txManager.getTransaction().enlistResource(roResource);
+  Answer answer2 = session.query(new Query(...));
+  Transaction tx3 = txManager.suspend();
+
+  // use answer2.
+  answer2.close();
+
+  /*
+   * Note the call to tx3.commit() is performed on a suspended transaction.  As
+   * tx3 is a handle to the transaction it does not need to be reassociated with
+   * the current thread as is required if it is going to be committed via the
+   * transaction manager.  This flexibility is mandated by JTA.
+   */
+  txManager.begin();
+  txManager.getTransaction().enlistResource(rwResource);
+  session.removeModel(...);
+  txManager.commit();
+  txManager.resume(tx2);
+  txManager.commit();
+  tx3.commit();
+  session.close();
+}

Modified: branches/mgr-61-sparql/jxdata/iTQL/backup_restore/backup1Result3.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/backup_restore/backup1Result3.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/backup_restore/backup1Result3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/backup_restore/result3.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/backup_restore/result3.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/backup_restore/result3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/backup_restore/test.jxu
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/backup_restore/test.jxu	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/backup_restore/test.jxu	2008-03-28 22:55:51 UTC (rev 723)
@@ -238,8 +238,6 @@
 <!--  BACKUP 3 - backup and restore the server locally  -->
 <!-- ================================================== -->
 
-<!--
-
   <set name="query" value="backup &lt;@server@&gt; to local &lt;@baseuri@/tmp/server.gz&gt;;"/>
 
   <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
@@ -248,6 +246,7 @@
     <fail>Output failed.  Check badQuery6Result.xml for output.</fail>
   </ifEqual>
 
+<!--
   <set name="query" value="restore &lt;@server@&gt; from local &lt;@baseuri@/tmp/server.gz&gt;;"/>
 
   <eval stepClass="org.mulgara.store.jxunit.QueryJX" />

Modified: branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult3.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult3.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#vcard2</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#vcard2</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult5.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult5.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/create_drop/queryResult5.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#vcard1</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#vcard1</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/base64Binary/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/base64Binary/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/base64Binary/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/hexBinary/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/hexBinary/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/binary/hexBinary/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/boolean/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/boolean/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/boolean/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/gDates/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/gDates/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/gDates/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult34.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult34.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult34.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,4 +1,4 @@
-ItqlInterpreter error - Could not commit insert
+ItqlInterpreter error - Could not commit modify
 Caused by: (QueryException) org.mulgara.query.MulgaraTransactionException: Transaction rollback triggered
 Caused by: (QueryException) org.mulgara.resolver.spi.ResolverException: Unable to read input statements
 Caused by: (QueryException) org.mulgara.query.TuplesException: Failed to localize node

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult37.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult37.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/queryResult37.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#unknowntype</message></query><query><message>Successfully inserted statements into @server@#unknowntype</message></query><query><variables><color/></variables><solution><color datatype="http://example.com/Color">pink</color></solution></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#unknowntype</message></query><query><message>Successfully inserted statements into @server@#unknowntype</message></query><query><variables><color/></variables><solution><color datatype="http://example.com/Color">pink</color></solution></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/data_types/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/data_types/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/data_types/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult10.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult10.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult10.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><variables><object/></variables></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><variables><object/></variables></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult11.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult11.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult11.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>mp3</object></solution><solution><object>mbox</object></solution><solution><object>Trash</object></solution><solution><object>Root</object></solution><solution><object>Repository</object></solution><solution><object>Normal</object></solution><solution><object>InvalidAttachments</object></solution><solution><object>Invalid</object></solution><solution><object>Entries</object></solution><solution><object>EmptyHeader</object></solution><solution><object>Empty</object></solution><solution><object>CouldBe</object></solution><solution><object>Chrono_Trigger_600_AD_in_Piano.mp3</object></solution><solution><object>CVS</object></solution><solution><object>BadSubject</object></solution><solution><object>Attachments</object></solution></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>mp3</object></solution><solution><object>mbox</object></solution><solution><object>Trash</object></solution><solution><object>Root</object></solution><solution><object>Repository</object></solution><solution><object>Normal</object></solution><solution><object>InvalidAttachments</object></solution><solution><object>Invalid</object></solution><solution><object>Entries</object></solution><solution><object>EmptyHeader</object></solution><solution><object>Empty</object></solution><solution><object>CouldBe</object></solution><solution><object>Chrono_Trigger_600_AD_in_Piano.mp3</object></solution><solution><object>CVS</object></solution><solution><object>BadSubject</object></solution><solution><object>Attachments</object></solution></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult12.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult12.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult12.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>mbox</object></solution><solution><object>Trash</object></solution><solution><object>Root</object></solution><solution><object>Repository</object></solution><solution><object>Normal</object></solution><solution><object>InvalidAttachments</object></solution><solution><object>Entries</object></solution><solution><object>EmptyHeader</object></solution><solution><object>CouldBe</object></solution><solution><object>CVS</object></solution><solution><object>BadSubject</object></solution><solution><object>Attachments</object></solution></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>mbox</object></solution><solution><object>Trash</object></solution><solution><object>Root</object></solution><solution><object>Repository</object></solution><solution><object>Normal</object></solution><solution><object>InvalidAttachments</object></solution><solution><object>Entries</object></solution><solution><object>EmptyHeader</object></solution><solution><object>CouldBe</object></solution><solution><object>CVS</object></solution><solution><object>BadSubject</object></solution><solution><object>Attachments</object></solution></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult8.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult8.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult8.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>ical.rdf</object></solution></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables><solution><object>ical.rdf</object></solution></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult9.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult9.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/queryResult9.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><variables><object/></variables></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/filesystem/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/filesystem/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/filesystem/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully dropped model @server@#fsmodel</message></query><query><message>Successfully created model @server@#fsmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query><query><message>Successfully dropped model @server@#xsdmodel</message></query><query><message>Successfully created model @server@#xsdmodel</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully dropped graph @server@#fsmodel</message></query><query><message>Successfully created graph @server@#fsmodel</message></query><query><message>Successfully aliased http://mulgara.org/mulgara# as exp</message></query><query><message>Successfully inserted statements into @server@?def#fsmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query><query><message>Successfully dropped graph @server@#xsdmodel</message></query><query><message>Successfully created graph @server@#xsdmodel</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/drop1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/drop1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/drop1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped model @server@#model1</message></query><query><message>Successfully dropped model @server@#fulltext</message></query><query><message>Successfully dropped model @server@#fulltext2</message></query><query><message>Successfully dropped model @server@#normal_zh</message></query><query><message>Successfully dropped model @server@#fulltext_zh</message></query><query><message>Successfully dropped model @server@#numbers_test</message></query><query><message>Successfully dropped model @server@#numbers_fulltext</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#model1</message></query><query><message>Successfully dropped graph @server@#fulltext</message></query><query><message>Successfully dropped graph @server@#fulltext2</message></query><query><message>Successfully dropped graph @server@#normal_zh</message></query><query><message>Successfully dropped graph @server@#fulltext_zh</message></query><query><message>Successfully dropped graph @server@#numbers_test</message></query><query><message>Successfully dropped graph @server@#numbers_fulltext</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/queryResult8.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/queryResult8.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/queryResult8.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#lucenetest</message></query><query><message>Successfully inserted statements into @server@#lucenetest</message></query><query><variables><page/></variables><solution><page resource="http://subject/"/></solution></query><query><message>Successfully dropped model @server@#lucenetest</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#lucenetest</message></query><query><message>Successfully inserted statements into @server@#lucenetest</message></query><query><variables><page/></variables><solution><page resource="http://subject/"/></solution></query><query><message>Successfully dropped graph @server@#lucenetest</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result2.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result2.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result2.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#fulltext</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#fulltext</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result3.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result3.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#fulltext2</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#fulltext2</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result5.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result5.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result5.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#numbers_fulltext</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#numbers_fulltext</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result7.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result7.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/fulltext_queries/result7.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#fulltext_zh</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#fulltext_zh</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/insert/queryResult1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/insert/queryResult1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/insert/queryResult1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#inserttest</message></query><query><message>Successfully inserted statements into @server@#inserttest</message></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://www.w3.org/2002/12/cal/ical#Vevent"/></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#categories"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#comment"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#created"/><o>2004-05-10T12:12:24</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#description"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtend"/><o>2004-05-10T08:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtstamp"/><o>2004-05-10T12:12:24</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtstart"/><o>2004-05-10T07:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#duration"/><o>01-01-01T00:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#lastmodified"/><o>2004-05-10T12:12:37</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#location"/><o>Here</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#sequence"/><o>1</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#summary"/><o>Summary</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#uid"/><o>1272862874444564481399228405</o></solution></query><query><message>Successfully dropped model @server@#inserttest</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#inserttest</message></query><query><message>Successfully inserted statements into @server@#inserttest</message></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://www.w3.org/2002/12/cal/ical#Vevent"/></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#categories"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#comment"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#created"/><o>2004-05-10T12:12:24</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#description"/><o></o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtend"/><o>2004-05-10T08:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtstamp"/><o>2004-05-10T12:12:24</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#dtstart"/><o>2004-05-10T07:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#duration"/><o>01-01-01T00:00:00</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#lastmodified"/><o>2004-05-10T12:12:37</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#location"/><o>Here</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#sequence"/><o>1</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#summary"/><o>Summary</o></solution><solution><p resource="http://www.w3.org/2002/12/cal/ical#uid"/><o>1272862874444564481399228405</o></solution></query><query><message>Successfully dropped graph @server@#inserttest</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/node_types/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/node_types/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/node_types/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully dropped model @server@#type</message></query><query><message>Successfully created model @server@#type</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully dropped graph @server@#type</message></query><query><message>Successfully created graph @server@#type</message></query></answer>

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser (from rev 722, trunk/jxdata/iTQL/parser)

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt
===================================================================
--- trunk/jxdata/iTQL/parser/createResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#parsertest</message></query></answer>

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt (from rev 722, trunk/jxdata/iTQL/parser/createResult.txt)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/createResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#parsertest</message></query></answer>

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt
===================================================================
--- trunk/jxdata/iTQL/parser/dropResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#parsertest</message></query></answer>

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt (from rev 722, trunk/jxdata/iTQL/parser/dropResult.txt)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/dropResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully dropped graph @server@#parsertest</message></query></answer>

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt
===================================================================
--- trunk/jxdata/iTQL/parser/insertResult1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +0,0 @@
-ItqlInterpreter error - [1,9] Unknown token: >
-Caused by: (LexerException) [1,9] Unknown token: >

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt (from rev 722, trunk/jxdata/iTQL/parser/insertResult1.txt)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2 @@
+ItqlInterpreter error - [1,9] Unknown token: >
+Caused by: (LexerException) [1,9] Unknown token: >

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt
===================================================================
--- trunk/jxdata/iTQL/parser/insertResult2.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +0,0 @@
-ItqlInterpreter error - [1,19] Unknown token: >
-Caused by: (LexerException) [1,19] Unknown token: >

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt (from rev 722, trunk/jxdata/iTQL/parser/insertResult2.txt)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult2.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2 @@
+ItqlInterpreter error - [1,19] Unknown token: >
+Caused by: (LexerException) [1,19] Unknown token: >

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt
===================================================================
--- trunk/jxdata/iTQL/parser/insertResult3.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +0,0 @@
-ItqlInterpreter error - [1,28] Unknown token: >
-Caused by: (LexerException) [1,28] Unknown token: >

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt (from rev 722, trunk/jxdata/iTQL/parser/insertResult3.txt)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/insertResult3.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2 @@
+ItqlInterpreter error - [1,28] Unknown token: >
+Caused by: (LexerException) [1,28] Unknown token: >

Deleted: branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu
===================================================================
--- trunk/jxdata/iTQL/parser/test.jxu	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,53 +0,0 @@
-<jxu>
-  <set name="debug" value="false" />
-
-  <set name="query" value="create &lt;@server@#parsertest&gt; ;"/>
-  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
-  <ifEqual converse="true" file="createResult.txt" name="queryResult">
-    <save name="queryResult" file="badCreateResult.xml"/>
-    <fail>Output failed.  Check badCreateResult.xml for output.</fail>
-  </ifEqual>
-
-  <set name="query" value="
-  insert &lt;&gt; &lt;foo:bar&gt; &lt;foo:a1&gt; 
-         &lt;&gt; &lt;foo:baz&gt; &lt;foo:a2&gt; 
-         &lt;&gt; &lt;foo:boz&gt; &lt;foo:a3&gt; 
-  into &lt;@server@#parsertest&gt; ;"/>
-
-  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
-  <ifEqual converse="true" file="insertResult1.txt" name="queryResult">
-    <save name="queryResult" file="badInsert1Result.xml"/>
-    <fail>Output failed.  Check badInsert1Result.xml for output.</fail>
-  </ifEqual>
-
-  <set name="query" value="
-  insert &lt;foo:bar&gt; &lt;&gt; &lt;foo:a1&gt; 
-         &lt;foo:baz&gt; &lt;&gt; &lt;foo:a2&gt; 
-         &lt;foo:boz&gt; &lt;&gt; &lt;foo:a3&gt; 
-  into &lt;@server@#parsertest&gt; ;"/>
-
-  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
-  <ifEqual converse="true" file="insertResult2.txt" name="queryResult">
-    <save name="queryResult" file="badInsert2Result.xml"/>
-    <fail>Output failed.  Check badInsert2Result.xml for output.</fail>
-  </ifEqual>
-
-  <set name="query" value="
-  insert &lt;foo:bar&gt; &lt;foo:a1&gt; &lt;&gt; 
-         &lt;foo:baz&gt; &lt;foo:a2&gt; &lt;&gt; 
-         &lt;foo:boz&gt; &lt;foo:a3&gt; &lt;&gt; 
-  into &lt;@server@#parsertest&gt; ;"/>
-
-  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
-  <ifEqual converse="true" file="insertResult3.txt" name="queryResult">
-    <save name="queryResult" file="badInsert3Result.xml"/>
-    <fail>Output failed.  Check badInsert3Result.xml for output.</fail>
-  </ifEqual>
-
-  <set name="query" value="drop &lt;@server@#parsertest&gt; ;"/>
-  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
-  <ifEqual converse="true" file="dropResult.txt" name="queryResult">
-    <save name="queryResult" file="badDropResult.xml"/>
-    <fail>Output failed.  Check badDropResult.xml for output.</fail>
-  </ifEqual>
-</jxu>

Copied: branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu (from rev 722, trunk/jxdata/iTQL/parser/test.jxu)
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu	                        (rev 0)
+++ branches/mgr-61-sparql/jxdata/iTQL/parser/test.jxu	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,53 @@
+<jxu>
+  <set name="debug" value="false" />
+
+  <set name="query" value="create &lt;@server@#parsertest&gt; ;"/>
+  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
+  <ifEqual converse="true" file="createResult.txt" name="queryResult">
+    <save name="queryResult" file="badCreateResult.xml"/>
+    <fail>Output failed.  Check badCreateResult.xml for output.</fail>
+  </ifEqual>
+
+  <set name="query" value="
+  insert &lt;&gt; &lt;foo:bar&gt; &lt;foo:a1&gt; 
+         &lt;&gt; &lt;foo:baz&gt; &lt;foo:a2&gt; 
+         &lt;&gt; &lt;foo:boz&gt; &lt;foo:a3&gt; 
+  into &lt;@server@#parsertest&gt; ;"/>
+
+  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
+  <ifEqual converse="true" file="insertResult1.txt" name="queryResult">
+    <save name="queryResult" file="badInsert1Result.xml"/>
+    <fail>Output failed.  Check badInsert1Result.xml for output.</fail>
+  </ifEqual>
+
+  <set name="query" value="
+  insert &lt;foo:bar&gt; &lt;&gt; &lt;foo:a1&gt; 
+         &lt;foo:baz&gt; &lt;&gt; &lt;foo:a2&gt; 
+         &lt;foo:boz&gt; &lt;&gt; &lt;foo:a3&gt; 
+  into &lt;@server@#parsertest&gt; ;"/>
+
+  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
+  <ifEqual converse="true" file="insertResult2.txt" name="queryResult">
+    <save name="queryResult" file="badInsert2Result.xml"/>
+    <fail>Output failed.  Check badInsert2Result.xml for output.</fail>
+  </ifEqual>
+
+  <set name="query" value="
+  insert &lt;foo:bar&gt; &lt;foo:a1&gt; &lt;&gt; 
+         &lt;foo:baz&gt; &lt;foo:a2&gt; &lt;&gt; 
+         &lt;foo:boz&gt; &lt;foo:a3&gt; &lt;&gt; 
+  into &lt;@server@#parsertest&gt; ;"/>
+
+  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
+  <ifEqual converse="true" file="insertResult3.txt" name="queryResult">
+    <save name="queryResult" file="badInsert3Result.xml"/>
+    <fail>Output failed.  Check badInsert3Result.xml for output.</fail>
+  </ifEqual>
+
+  <set name="query" value="drop &lt;@server@#parsertest&gt; ;"/>
+  <eval stepClass="org.mulgara.store.jxunit.QueryJX" />
+  <ifEqual converse="true" file="dropResult.txt" name="queryResult">
+    <save name="queryResult" file="badDropResult.xml"/>
+    <fail>Output failed.  Check badDropResult.xml for output.</fail>
+  </ifEqual>
+</jxu>

Modified: branches/mgr-61-sparql/jxdata/iTQL/prefix/result1.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/prefix/result1.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/prefix/result1.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#prefix</message></query><query><message>Successfully dropped model @server@#prefix</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#prefix</message></query><query><message>Successfully dropped graph @server@#prefix</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-container-membership-superProperty/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-container-membership-superProperty/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-container-membership-superProperty/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-domain-and-range/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-domain-and-range/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-domain-and-range/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subClassOf/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subClassOf/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subClassOf/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subPropertyOf/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subPropertyOf/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-no-cycles-in-subPropertyOf/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-subPropertyOf-semantics/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-subPropertyOf-semantics/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/rdfs-subPropertyOf-semantics/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/rdfs/statement-entailment/configResult.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/rdfs/statement-entailment/configResult.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/rdfs/statement-entailment/configResult.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created model @server@#type</message></query><query><message>Successfully created model @server@#prefix</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Successfully created graph @server@#type</message></query><query><message>Successfully created graph @server@#prefix</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/standard_queries/queryResult17.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/standard_queries/queryResult17.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/standard_queries/queryResult17.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,3 +1,3 @@
-ItqlInterpreter error - Could not commit insert
+ItqlInterpreter error - Could not commit modify
 Caused by: (QueryException) org.mulgara.query.MulgaraTransactionException: Transaction rollback triggered
 Caused by: (QueryException) rmi://localhost/server1#nomodelexistswiththisname is not a Model

Modified: branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult6.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult6.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult6.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully dropped model @server@#trans1</message></query><query><message>Successfully created model @server@#trans2</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully rolled back changes</message></query><query><message>Auto commit is on</message></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><variables><p/><o/></variables></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully dropped graph @server@#trans1</message></query><query><message>Successfully created graph @server@#trans2</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully rolled back changes</message></query><query><message>Auto commit is on</message></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><variables><p/><o/></variables></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult7.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult7.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult7.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully dropped model @server@#trans1</message></query><query><message>Successfully created model @server@#trans2</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully committed transaction</message></query><query><message>Auto commit is on</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully dropped model @server@#trans2</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully dropped graph @server@#trans1</message></query><query><message>Successfully created graph @server@#trans2</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully committed transaction</message></query><query><message>Auto commit is on</message></query><query><variables><p/><o/></variables></query><query><variables><p/><o/></variables><solution><p resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/><o resource="http://mulgara.org/mulgara#Model"/></solution></query><query><message>Successfully dropped graph @server@#trans2</message></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult8.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult8.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult8.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully created model @server@#trans3</message></query><query><message>Successfully inserted statements into @server@#trans3</message></query><query><variables><s/><o/></variables><solution><s resource="uri:subject1"/><o>1</o></solution></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully created graph @server@#trans3</message></query><query><message>Successfully inserted statements into @server@#trans3</message></query><query><variables><s/><o/></variables><solution><s resource="uri:subject1"/><o>1</o></solution></query></answer>

Modified: branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult9.txt
===================================================================
--- branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult9.txt	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/jxdata/iTQL/transactions/queryResult9.txt	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully created model @server@#trans3</message></query><query><message>Successfully inserted statements into @server@#trans3</message></query><query><variables><s/><o/></variables><solution><s resource="uri:subject1"/><o>1</o></solution></query><query><message>Successfully dropped model @server@#trans3</message></query><query><message>Auto commit is on</message></query></answer>
+<answer xmlns="http://mulgara.org/tql#"><query><message>Auto commit is off</message></query><query><message>Successfully created graph @server@#trans3</message></query><query><message>Successfully inserted statements into @server@#trans3</message></query><query><variables><s/><o/></variables><solution><s resource="uri:subject1"/><o>1</o></solution></query><query><message>Successfully dropped graph @server@#trans3</message></query><query><message>Auto commit is on</message></query></answer>

Modified: branches/mgr-61-sparql/lib/antlr.jar
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/axis-1.1.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/axis-1.4.jar (from rev 722, trunk/lib/axis-1.4.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/axis-ant-1.1.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/axis-ant-1.4.jar (from rev 722, trunk/lib/axis-ant-1.4.jar)
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/carol-2.0.5.jar (from rev 722, trunk/lib/carol-2.0.5.jar)
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/howl-logger-0.1.11.jar (from rev 722, trunk/lib/howl-logger-0.1.11.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/jaxrpc-1.1.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/jaxrpc-1.4.jar (from rev 722, trunk/lib/jaxrpc-1.4.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/jotm-1.5.3-patched.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/jotm-2.0.10.jar (from rev 722, trunk/lib/jotm-2.0.10.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/jotm_carol-1.5.3.jar
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/jotm_iiop_stubs-1.5.3.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/jotm_jrmp_stubs-2.0.10.jar (from rev 722, trunk/lib/jotm_jrmp_stubs-2.0.10.jar)
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/log4j-1.2.15.jar (from rev 722, trunk/lib/log4j-1.2.15.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/log4j-1.2.8.jar
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/saaj-1.1.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/saaj-1.4.jar (from rev 722, trunk/lib/saaj-1.4.jar)
===================================================================
(Binary files differ)

Deleted: branches/mgr-61-sparql/lib/wsdl4j-1.4.jar
===================================================================
(Binary files differ)

Copied: branches/mgr-61-sparql/lib/wsdl4j-1.5.1.jar (from rev 722, trunk/lib/wsdl4j-1.5.1.jar)
===================================================================
(Binary files differ)

Modified: branches/mgr-61-sparql/src/jar/ant-task/java/org/mulgara/ant/task/rdf/RDFLoad.java
===================================================================
--- branches/mgr-61-sparql/src/jar/ant-task/java/org/mulgara/ant/task/rdf/RDFLoad.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/ant-task/java/org/mulgara/ant/task/rdf/RDFLoad.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -517,7 +517,7 @@
    */
   protected void createModel() throws BuildException {
     executeQuery("create <" + modelURI + "> ;", "create model",
-                 "Successfully created model ");
+                 "Successfully created graph ");
   }
 
   /**
@@ -527,7 +527,7 @@
    */
   protected void dropModel() throws BuildException {
     executeQuery("drop <" + modelURI + "> ;", "drop model",
-                 "Successfully dropped model ");
+                 "Successfully dropped graph ");
   }
 
   /**

Modified: branches/mgr-61-sparql/src/jar/client-jrdf/java/org/mulgara/client/jrdf/test/ClientGraphUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/client-jrdf/java/org/mulgara/client/jrdf/test/ClientGraphUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/client-jrdf/java/org/mulgara/client/jrdf/test/ClientGraphUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import junit.framework.*;
 
 //Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // JRDF
 import org.jrdf.graph.*;
@@ -75,8 +75,7 @@
   /**
    * the category to send logging info to
    */
-  private static Category log =
-      Category.getInstance(ClientGraphUnitTest.class.getName());
+  private static Logger log = Logger.getLogger(ClientGraphUnitTest.class);
 
   /**
    * Server to query against.

Modified: branches/mgr-61-sparql/src/jar/config/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/config/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/config/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -9,7 +9,7 @@
   <!-- =================================================================== -->
   <!-- Builds the base Mulgara configuration JAR                            -->
   <!-- =================================================================== -->
-  <target name="config-generate-uptodate">
+  <target name="-config-generate-uptodate">
 
     <condition property="config-generate-uptodate">
       <and>
@@ -21,8 +21,8 @@
     </condition>
   </target>
 
-  <target name="config-generate"
-     description="Generates the Mulgara config code" unless="config-generate-uptodate">
+  <target name="config-generate" description="Generates the Mulgara config code"
+      depends="-config-generate-uptodate" unless="config-generate-uptodate">
 
     <delete dir="${obj.dir}/jar/config/java"/>
 

Modified: branches/mgr-61-sparql/src/jar/content-mbox/java/org/mulgara/content/mbox/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-mbox/java/org/mulgara/content/mbox/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-mbox/java/org/mulgara/content/mbox/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -160,8 +160,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
 
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/content-mp3/java/org/mulgara/content/mp3/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-mp3/java/org/mulgara/content/mp3/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-mp3/java/org/mulgara/content/mp3/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -160,7 +160,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/Parser.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/Parser.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/Parser.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -517,9 +517,11 @@
    */
   private BlankNodeImpl createBlankNode() {
     try {
-      return new BlankNodeImpl(resolverSession.newBlankNode());
-    } catch (NodePoolException npe) {
-      throw new RuntimeException("Unable to create blank node", npe);
+      BlankNodeImpl bn = new BlankNodeImpl();
+      resolverSession.localize(bn);  // This sets and returns the node ID
+      return bn;
+    } catch (LocalizeException le) {
+      throw new RuntimeException("Unable to create blank node", le);
     }
   }
 

Modified: branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-n3/java/org/mulgara/content/n3/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -144,7 +144,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -144,7 +144,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/writer/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/writer/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-rdfxml/java/org/mulgara/content/rdfxml/writer/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -172,7 +172,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/content-rio/java/org/mulgara/content/rio/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/content-rio/java/org/mulgara/content/rio/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/content-rio/java/org/mulgara/content/rio/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -144,7 +144,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/demo-mp3/java/org/mulgara/demo/mp3/swing/Mp3Application.java
===================================================================
--- branches/mgr-61-sparql/src/jar/demo-mp3/java/org/mulgara/demo/mp3/swing/Mp3Application.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/demo-mp3/java/org/mulgara/demo/mp3/swing/Mp3Application.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -499,7 +499,7 @@
     try {
       // Just use the basic Log configurator
       BasicConfigurator.configure();
-      Category.getRoot().setLevel(Level.WARN);
+      Logger.getRootLogger().setLevel(Level.WARN);
       // create an Application
       String config = Mp3Application.DEFAULT_CONFIG_FILE;
       if (args.length > 0) {

Modified: branches/mgr-61-sparql/src/jar/descriptor/src/java/org/mulgara/descriptor/PIErrorHandler.java
===================================================================
--- branches/mgr-61-sparql/src/jar/descriptor/src/java/org/mulgara/descriptor/PIErrorHandler.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/descriptor/src/java/org/mulgara/descriptor/PIErrorHandler.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 
 import javax.xml.transform.*;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.xml.sax.*;
 import org.xml.sax.helpers.LocatorImpl;
 
@@ -68,7 +68,7 @@
   /**
    * Description of the Field
    */
-  private static Category log = Category.getInstance("XALAN");
+  private static final Logger log = Logger.getLogger("XALAN");
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/itql/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -87,7 +87,7 @@
     </manifest>
     <manifest file="${obj.dir}/META-INF/MANIFEST_ITQL_BOOTSTRAP.MF">
       <attribute name="Main-Class" value="org.mulgara.util.Bootstrap"/>
-      <attribute name="Embedded-Jar" value="${query.jar}, ${driver.jar}, ${itql.jar},${util.jar}, ${server-beep.jar}, ${server-rmi.jar}, apache-soap-2.2.jar, log4j-1.2.8.jar,jargs-0.2.jar, ${jrdf.jar}, ${saaj.jar}, ${emory-util.jar}"/>
+      <attribute name="Embedded-Jar" value="${query.jar}, ${driver.jar}, ${itql.jar},${util.jar}, ${server-beep.jar}, ${server-rmi.jar}, apache-soap-2.2.jar, log4j-1.2.15.jar,jargs-0.2.jar, ${jrdf.jar}, ${saaj.jar}, ${emory-util.jar}"/>
       <attribute name="Embedded-Main-Class" value="org.mulgara.itql.TqlSession"/>
     </manifest>
   </target>
@@ -120,7 +120,7 @@
     <jar jarfile="${dist.dir}/${itql.jar}"
          manifest="${obj.dir}/META-INF/itql-MANIFEST.MF">
 
-      <fileset dir="${conf.dir}" includes="log4j-itql.xml"/>
+      <fileset dir="${conf.dir}" includes="log4j-tql.xml"/>
       <fileset dir="${itql.src.dir}/itql"
                includes="default-pre.itql, default-post.itql"/>
 
@@ -138,7 +138,7 @@
       <zipfileset src="${lib.dir}/${jrdf.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/jsr173_07_api.jar" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/jsr173_07_ri.jar" excludes="META-INF/**"/>
-      <zipfileset src="${lib.dir}/log4j-1.2.8.jar" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/log4j-1.2.15.jar" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${saaj.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${emory-util.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jta.jar}" excludes="META-INF/**"/>

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/Collaborator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/Collaborator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/Collaborator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -803,7 +803,7 @@
   public synchronized boolean createModel() throws SOAPException {
 
     log.warn("creating model " + SERVER + MODEL);
-    return executeCommand(CREATE_MODEL, "Successfully created model", false);
+    return executeCommand(CREATE_MODEL, "Successfully created graph", false);
   }
 
   /**
@@ -815,7 +815,7 @@
   public synchronized boolean dropModel() throws SOAPException {
 
     log.warn("dropping model " + SERVER + MODEL);
-    return executeCommand(DROP_MODEL, "Successfully dropped model", false);
+    return executeCommand(DROP_MODEL, "Successfully dropped graph", false);
   }
 
   /**

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/CollaboratorUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/CollaboratorUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/CollaboratorUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 // Third party packages
 import java.io.IOException;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.soap.SOAPException;
 
 /**
@@ -62,7 +62,7 @@
 
   /** Logger. */
   @SuppressWarnings("unused")
-  private final static Category logger = Category.getInstance(CollaboratorUnitTest.class.getName());
+  private final static Logger logger = Logger.getLogger(CollaboratorUnitTest.class);
 
   /**
    * a flag to indicate if the collorator requires closing

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/HelpPrinter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/HelpPrinter.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/HelpPrinter.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.itql;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Automatically generated packages (SableCC)
 import org.mulgara.itql.analysis.DepthFirstAdapter;
@@ -63,8 +63,7 @@
   /**
    * the category to log to
    */
-  private final static Category log =
-      Category.getInstance(HelpPrinter.class.getName());
+  private final static Logger log = Logger.getLogger(HelpPrinter.class);
 
   /**
    * Get line separator.

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBean.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBean.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBean.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -278,7 +278,6 @@
 
     if (log.isDebugEnabled()) log.debug("Begin transaction for :" + name);
 
-    if (legacySession != null) legacySession.setAutoCommit(false);
     SetAutoCommit autocommitCmd = new SetAutoCommit(false);
     try {
       // do what the autointerpreter does, but don't worry about the result
@@ -303,8 +302,6 @@
 
     if (log.isDebugEnabled()) log.debug("Commit transaction for :" + name);
 
-    // this is the same as a commit call
-    if (legacySession != null) legacySession.setAutoCommit(true);
     interpreter.commitAll();
   }
 
@@ -320,10 +317,6 @@
 
     log.warn("Rollback transaction for :" + name);
 
-    if (legacySession != null) {
-      legacySession.rollback();
-      legacySession.setAutoCommit(true);
-    }
     interpreter.rollbackAll();
   }
 
@@ -623,12 +616,9 @@
 
 
   /**
-   * Returns true if a quit command has been entered, simply calls the
-   * interpreter.isQuitRequested.
+   * Returns true if a quit command has been entered.
    *
    * @return true if a quit command has been entered
-   *
-   * @see ItqlInterpreter#isQuitRequested()
    */
   public boolean isQuitRequested() {
     return quit;
@@ -636,13 +626,13 @@
 
 
   /**
-   * Returns the {@linkplain ItqlInterpreter#getLastMessage last message} of
+   * Returns the {@linkplain TqlAutoInterpreter#getLastMessage last message} of
    * the interpreter.
    *
    * @return the results of the last command execution, null if the command did
    *      not set any message
    *
-   * @see ItqlInterpreter#getLastMessage()
+   * @see TqlAutoInterpreter#getLastMessage()
    */
   public String getLastMessage() {
     return interpreter.getLastMessage();
@@ -650,15 +640,15 @@
 
 
   /**
-   * Returns the {@linkplain ItqlInterpreter#getLastException last error} of the
-   * interpreter.
+   * Returns the {@linkplain TqlAutoInterpreter#getLastException last error} of
+   * the interpreter.
    *
    * @return the results of the last command execution, null if the command did
    *      not set any message
    *
-   * @see ItqlInterpreter#getLastException()
+   * @see TqlAutoInterpreter#getLastException()
    */
-  public ItqlInterpreterException getLastException() {
+  public ItqlInterpreterException getLastError() {
     return new ItqlInterpreterException(interpreter.getLastException());
   }
 

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBeanUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBeanUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlInterpreterBeanUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,6 +29,8 @@
 
 import org.mulgara.query.Answer;
 import org.mulgara.query.QueryException;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
 import org.mulgara.util.TempDir;
 
 // third party packages
@@ -46,7 +48,7 @@
 // third party packages
 import javax.xml.parsers.FactoryConfigurationError;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.log4j.xml.DOMConfigurator; // Soap packages
 
 // Soap packages
@@ -83,7 +85,7 @@
   //
 
   /** The category to send logging info to */
-  private static Category log = Category.getInstance(ItqlInterpreterBeanUnitTest.class.getName());
+  private static final Logger log = Logger.getLogger(ItqlInterpreterBeanUnitTest.class);
 
   /** Description of the Field */
   private ItqlInterpreterBean bean = null;
@@ -159,6 +161,7 @@
     suite.addTest(new ItqlInterpreterBeanUnitTest("testRestoreApi1"));
     suite.addTest(new ItqlInterpreterBeanUnitTest("testRoundTrip1"));
     suite.addTest(new ItqlInterpreterBeanUnitTest("testMultipleBeanTest"));
+    suite.addTest(new ItqlInterpreterBeanUnitTest("testExplicitSession"));
 
     return suite;
   }
@@ -396,7 +399,7 @@
     // execute the load remotely
     long statements = bean.load(null, sourceURI, modelURI);
 
-    assertEquals("Incorrect number of statements inserted", 146, statements);
+    assertEquals("Incorrect number of statements inserted", 154, statements);
   }
 
   // testLoadApi1()
@@ -427,7 +430,7 @@
     long statements = bean.load(inputStream,
         sourceURI, modelURI);
 
-    assertEquals("Incorrect number of statements inserted", 146, statements);
+    assertEquals("Incorrect number of statements inserted", 154, statements);
 
     inputStream.close();
 
@@ -454,7 +457,7 @@
     long statements = bean.load(sourceURI.toURL().openStream(),
         dummyURI, modelURI);
 
-    assertEquals("Incorrect number of statements inserted", 146, statements);
+    assertEquals("Incorrect number of statements inserted", 154, statements);
 
   }
 
@@ -475,7 +478,7 @@
     long statements = bean.load(sourceURI.toURL().openStream(),
         modelURI);
 
-    assertEquals("Incorrect number of statements inserted", 146, statements);
+    assertEquals("Incorrect number of statements inserted", 154, statements);
 
   }
 
@@ -825,6 +828,76 @@
      */
   }
 
+  /**
+   * Test giving ItqlInterpreterBean an explicit session.
+   *
+   * @throws Exception if the test fails
+   */
+  public void testExplicitSession() throws Exception {
+
+    // log that we're executing the test
+    log.debug("Starting explicit session test");
+
+    URI serverURI = new URI("rmi://" + hostName + "/server1");
+    SessionFactory sessionFactory =
+                      SessionFactoryFinder.newSessionFactory(serverURI, true);
+
+    bean.close();
+    bean = new ItqlInterpreterBean(sessionFactory.newSession(),
+                                   sessionFactory.getSecurityDomain());
+
+    // auto-commit = true
+    bean.executeQuery(
+        "insert <es:foo1> <es:bar1> 'foo' into <" + testModel + ">;");
+
+    Answer answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting a single result", 1, answer.getRowCount());
+
+    bean.executeQuery(
+        "delete <es:foo1> <es:bar1> 'foo' from <" + testModel + ">;");
+
+    answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting no results", 0, answer.getRowCount());
+
+    // explicit tx with commit
+    bean.beginTransaction("explicit-session-test-commit");
+
+    bean.executeQuery(
+        "insert <es:foo1> <es:bar1> 'foo' into <" + testModel + ">;");
+
+    answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting a single result", 1, answer.getRowCount());
+
+    bean.executeQuery(
+        "delete <es:foo1> <es:bar1> 'foo' from <" + testModel + ">;");
+
+    bean.commit("explicit-session-test-commit");
+
+    answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting no results", 0, answer.getRowCount());
+
+    // explicit tx with rollback
+    bean.beginTransaction("explicit-session-test-rollback");
+
+    bean.executeQuery(
+        "insert <es:foo1> <es:bar1> 'foo' into <" + testModel + ">;");
+
+    answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting a single result", 1, answer.getRowCount());
+
+    bean.rollback("explicit-session-test-rollback");
+
+    answer = bean.executeQuery(
+        "select $p $o from <" + testModel + "> " + "where <es:foo1> $p $o;");
+    assertEquals("Expecting no results", 0, answer.getRowCount());
+  }
+
+
   // ItqlInt
 
   /**

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlOptionParser.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlOptionParser.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlOptionParser.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import jargs.gnu.CmdLineParser;
 
 // third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Command line option parser for the iTQL interpreter.
@@ -114,8 +114,7 @@
   /**
    * the category to log to
    */
-  private final static Category log =
-      Category.getInstance(ItqlOptionParser.class.getName());
+  private final static Logger log = Logger.getLogger(ItqlOptionParser.class);
 
   //
   // members

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/ItqlSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 
 // Third party packages
 import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.log4j.xml.DOMConfigurator;
 
 // Automatically generated packages (SableCC)
@@ -103,8 +103,7 @@
   /**
    * the logging category to log to
    */
-  private final static Category log =
-      Category.getInstance(ItqlSession.class.getName());
+  private final static Logger log = Logger.getLogger(ItqlSession.class);
 
   /**
    * the default path to the pre-loading script

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/SableCCInterpreter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/SableCCInterpreter.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/SableCCInterpreter.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -76,7 +76,7 @@
    *
    * @param token  the token to be converted, which should actually be a
    *   {@link TResource}
-   * @throws Error if the <var>token</var> text isn't syntactically
+   * @throws RuntimeException if the <var>token</var> text isn't syntactically
    *   a {@link URI}; this shouldn't ever occur, assuming the <var>token</var>
    *   is a {@link TResource}
    */

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -159,6 +159,8 @@
     aliases.put(MULGARA, URI.create(MULGARA_NS));
     aliases.put(KRULE, URI.create(KRULE_NS));
     aliases.put(DC, URI.create(DC_NS));
+    aliases.put(SKOS, URI.create(SKOS_NS));
+    aliases.put(FOAF, URI.create(FOAF_NS));
     return aliases;
   }  
 
@@ -483,6 +485,21 @@
 
 
   /**
+   * Requests a list of current aliases.
+   *
+   * @param node the alias command
+   */
+  public void outAAliaslCommand(AAliaslCommand node) {
+
+    // log the command
+    if (logger.isDebugEnabled()) logger.debug("Processing alias list command " + node);
+
+    // Return an AST element, for reporting on what happened.
+    // Use a Help command, with the alias listing as the help text.
+    lastCommand = new Help(buildAliasList());
+  }
+
+  /**
    * Applies a set of rules in a model to data in another model.
    *
    * @param node the alias command
@@ -814,7 +831,7 @@
 
     // build the variable list: collection of Variable, ConstantValue, Count, Subquery
     if (logger.isDebugEnabled()) logger.debug("Building query variable list from " + variables);
-    List<Object> variableList = this.buildVariableList(variables);
+    List<SelectElement> variableList = this.buildVariableList(variables);
     if (logger.isDebugEnabled()) logger.debug("Built variable list " + variableList);
   
     // get the model expression from the parser
@@ -999,11 +1016,11 @@
    *      into a list of {@link org.mulgara.query.Variable}s
    */
   @SuppressWarnings("unchecked")
-  List<Object> buildVariableList(LinkedList<PElement> rawVariableList) throws
+  List<SelectElement> buildVariableList(LinkedList<PElement> rawVariableList) throws
       QueryException, URISyntaxException {
   
     // Empty variable list.
-    if (rawVariableList == null) return (List<Object>)Collections.EMPTY_LIST;
+    if (rawVariableList == null) return Collections.emptyList();
   
     // validate rawVariableList parameter
     if (rawVariableList.size() == 0) throw new IllegalArgumentException("Empty \"rawVariableList\" parameter");
@@ -1019,7 +1036,7 @@
     for (PElement element: rawVariableList) element.apply((Switch)variableBuilder);
   
     // Get the variable list
-    List<Object> variableList = variableBuilder.getVariableList();
+    List<SelectElement> variableList = variableBuilder.getVariableList();
   
     // make sure that we return a list with something in it
     if (variableList.size() == 0) {
@@ -1306,6 +1323,19 @@
 
 
   /**
+   * Writes the alias map as a set of URI/namespace pairs to a string for printing.
+   * @return A String containing all the alias mappings.
+   */
+  private String buildAliasList() {
+    StringBuilder buffer = new StringBuilder();
+    for (Map.Entry<String,URI> alias: getAliasMap().entrySet()) {
+      buffer.append(alias.getKey()).append(":  <").append(alias.getValue()).append(">\n");
+    }
+    return buffer.toString();
+  }
+
+
+  /**
    * Log the TQL command to a specified file
    *
    * @param command The TQL command to be validated

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/TqlSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -27,7 +27,7 @@
 
 // Third party packages
 import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.log4j.xml.DOMConfigurator;
 
 import org.mulgara.query.Answer;
@@ -65,7 +65,7 @@
   private final static String LOG4J_CONFIG_PATH = "log4j-tql.xml";
 
   /** The logging category to use */
-  private final static Category log = Category.getInstance(TqlSession.class.getName());
+  private final static Logger log = Logger.getLogger(TqlSession.class);
 
   /** The default path to the pre-loading script */
   private final static String PRE_LOADING_SCRIPT_PATH = "default-pre.tql";

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/URIUtil.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/URIUtil.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/URIUtil.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -44,7 +44,7 @@
       }
       return uri;
     } catch (URISyntaxException e) {
-      throw new Error("Bad URI syntax in resource: " + e);
+      throw new RuntimeException("Bad URI syntax in resource", e);
     }
   }
   

Modified: branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -78,7 +78,7 @@
    * The list of variables - these are mixed object types:
    * ConstantValue, Variable, Count, SubQuery
    */
-  private List<Object> variableList;
+  private List<SelectElement> variableList;
 
   /** The TQL interpreter */
   private SableCCInterpreter interpreter;
@@ -90,7 +90,7 @@
    * @param newInterpreter the interpreter to use.
    */
   public VariableBuilder(SableCCInterpreter newInterpreter, VariableFactory newVariableFactory) {
-    variableList = new ArrayList<Object>();
+    variableList = new ArrayList<SelectElement>();
     interpreter = newInterpreter;
     variableFactory = newVariableFactory;
   }
@@ -182,9 +182,9 @@
    * @throws URISyntaxException if the variable contains a resource whose
    *   text violates <a href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
    */
-  public List<Object> getVariableList() throws QueryException, URISyntaxException {
+  public List<SelectElement> getVariableList() throws QueryException, URISyntaxException {
     try {
-      List<Object> tmpVariableList = new ArrayList<Object>(variableList);
+      List<SelectElement> tmpVariableList = new ArrayList<SelectElement>(variableList);
 
       if (uriException != null) throw uriException;
       else if (queryException != null) throw queryException;

Modified: branches/mgr-61-sparql/src/jar/itql/sablecc/itql.grammar
===================================================================
--- branches/mgr-61-sparql/src/jar/itql/sablecc/itql.grammar	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/itql/sablecc/itql.grammar	2008-03-28 22:55:51 UTC (rev 723)
@@ -23,7 +23,8 @@
   com,  /* comment */
   esc,  /* escaping character in quoted literal with '\' */
   lit,  /* quoted literal */
-  res,  /* tagged resource */
+  begres,  /* start of tagged resource */
+  endres,  /* end of tagged resource */
   var,  /* escaping variable name with '$' */
   lng;  /* language code */
 
@@ -89,8 +90,8 @@
   {def}                terminator = ';';
   {def}                lpar       = '(';
   {def}                rpar       = ')';
-  {def->res}           url        = '<';
-  {res->def}           endurl     = '>';
+  {def->begres}        url        = '<';
+  {endres->def}        endurl     = '>';
   {def}                datatypeprefix = '^^';
   {def->lng}           languageprefix = '@';
   {def->var}           variableprefix = ('$' | '?');
@@ -98,7 +99,7 @@
   {def}                float      = digit+ ('.' digit*) | ('.' digit+);
   {lng->def}           langid      = letter letter | letter letter '-' letter letter;
 
-  {res}                resource    = urlchar*;
+  {begres->endres}     resource    = urlchar*;
   {def->lit, lit->def} quote       = 39;  /* ' */
   {lit->esc}           escape      = '\';
   {esc->lit}           escapedtext = character;
@@ -120,6 +121,7 @@
 
   command =
     {alias}     alias [target]:resource as [prefix]:identifier               |
+    {aliasl}    alias                                                        |
     {apply}     apply [rules]:resource to [base]:resource [destination]:resource? |
     {backup}    backup [source]:resource to [locality]:locality? [destination]:resource |
     {commit}    commit                                                       |

Modified: branches/mgr-61-sparql/src/jar/krule/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/krule/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/krule/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -27,6 +27,7 @@
     <pathelement path="${itql.dist.dir}/${itql.jar}"/>
     <pathelement path="${tuples.dist.dir}/${tuples.jar}"/>
     <pathelement path="${rules.dist.dir}/${rules.jar}"/>
+    <pathelement path="${resolver.dist.dir}/${resolver.jar}"/>
   </path>
 
   <path id="krule-test-classpath">
@@ -57,7 +58,7 @@
   </target>
 
   <target name="krule-compile"
-          depends="-krule-prepare, driver-jar, itql-jar, rules-jar, tuples-jar"
+          depends="-krule-prepare, driver-jar, itql-jar, rules-jar, tuples-jar, resolver-jar"
           description="Compiles all krule related files included generated source code">
 
     <javac destdir="${krule.obj.dir}/classes" debug="on"

Modified: branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/KruleLoader.java
===================================================================
--- branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/KruleLoader.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/KruleLoader.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -42,8 +42,8 @@
 import org.mulgara.query.rdf.LiteralImpl;
 import org.mulgara.query.rdf.TripleImpl;
 import org.mulgara.query.rdf.URIReferenceImpl;
+import org.mulgara.resolver.OperationContext;
 import org.mulgara.rules.*;
-import org.mulgara.server.*;
 
 /**
  * This object is used for parsing an RDF graph and building a rules structure
@@ -66,7 +66,7 @@
   private URI systemModel;
 
   /** The database session for querying. */
-  private Session session;
+  private OperationContext operationContext;
 
   /** The interpreter for parsing queries. */
   private TqlInterpreter interpreter;
@@ -204,7 +204,7 @@
     this.destModel = destModel;
 
     // set the query objects to null
-    session = null;
+    operationContext = null;
     interpreter = null;
 
     // initialize the aliases
@@ -231,13 +231,13 @@
   /**
    * Reads the ruleModel in the database and constructs the rules from it.
    *
-   * @param sessionParam The session for querying on.
+   * @param opContextParam The operationContext for querying on.
    * @param systemModel The system model.
    * @return A new rule structure.
    * @throws InitializerException There was a problem reading and creating the rules.
    */
-  public Rules readRules(Object sessionParam, URI systemModel) throws InitializerException, RemoteException {
-    this.session = (Session)sessionParam;
+  public Rules readRules(Object opContextParam, URI systemModel) throws InitializerException, RemoteException {
+    this.operationContext = (OperationContext)opContextParam;
     this.systemModel = systemModel;
 
     // get a new interpreter
@@ -245,7 +245,6 @@
 
     rules = null;
     try {
-      session.setAutoCommit(false);
       logger.debug("Initializing for rule queries.");
       // initialise the utility models
       initializeUtilityModels();
@@ -255,8 +254,7 @@
 
       logger.debug("Querying for rules");
       rules = findRules();
-      // set the base and target models
-      rules.setBaseModel(baseModel);
+      // set the target model
       rules.setTargetModel(destModel);
 
       // find the triggers
@@ -284,13 +282,6 @@
     } catch (Throwable t) {
       logger.error("Unexpected error during loading: " + t.getMessage(), t);
       throw new InitializerException("Unexpected error loading rules", t);
-    } finally {
-      try {
-        session.setAutoCommit(true);
-      } catch (QueryException e) {
-        logger.error("Unable to close transaction.", e);
-        throw new InitializerException("Unable to close transaction", e);
-      }
     }
 
     return rules;
@@ -337,7 +328,7 @@
       throw new QueryException("Invalid query.", e);
     }
     
-    Answer ruleAnswer = session.query(query);
+    Answer ruleAnswer = query(query);
     logger.debug("Got response for rule query");
 
     // create the rule structure for all the rules
@@ -372,7 +363,7 @@
       throw new QueryException("Invalid query.", e);
     }
 
-    Answer answer = session.query(query);
+    Answer answer = query(query);
 
     try {
       // link all the rules together
@@ -415,7 +406,7 @@
       } catch (Exception e) {
         throw new QueryException("Invalid query.", e);
       }
-      Answer answer = session.query(query);
+      Answer answer = query(query);
 
       // get the length of the sequence prefix
       int prefixLength = ((URI)aliases.get("rdf")).toString().length() + 1;
@@ -441,7 +432,15 @@
       }
       for (int select = 0; select < elements.length; select++) {
         if (elements[select] == null || types[select] == null) {
-          throw new KruleStructureException("Rule " + rule.getName() + " does not have enough insertion elements");
+          // one element was set. Get a descriptive error message
+          StringBuffer errorMsg = new StringBuffer();
+          for (int s = 0; s < elements.length; s++) {
+            if (elements[s] == null) errorMsg.append(" <null>");
+            else errorMsg.append(" ").append(elements[s]);
+            if (types[s] == null) errorMsg.append("^^<null>");
+            else errorMsg.append("^^<").append(types[s]).append(">");
+          }
+          throw new KruleStructureException("Rule " + rule.getName() + " does not have enough insertion elements. Got: " + errorMsg);
         }
       }
       // convert these elements into ConstraintElements for the query
@@ -455,7 +454,7 @@
       } catch (Exception e) {
         throw new QueryException("Invalid query.", e);
       }
-      answer = session.query(query);
+      answer = query(query);
 
       try {
         // attach the correct constraint tree to the query structure
@@ -510,7 +509,7 @@
     } catch (Exception e) {
       throw new QueryException("Invalid query.", e);
     }
-    Answer answer = session.query(query);
+    Answer answer = query(query);
 
     // prepare the set of axioms
     Set<org.jrdf.graph.Triple> axioms = new HashSet<org.jrdf.graph.Triple>();
@@ -591,7 +590,7 @@
       throw new QueryException("Invalid query.", e);
     }
     
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found prefix models");
 
     try {
@@ -627,7 +626,7 @@
       throw new QueryException("Invalid query.", e);
     }
     
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all URI references.");
 
     // create the mapping
@@ -666,7 +665,7 @@
       throw new QueryException("Invalid query.", e);
     }
     
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all variable references.");
 
     // create the mapping
@@ -705,7 +704,7 @@
       throw new QueryException("Invalid query.", e);
     }
     
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all Literals.");
 
     // create the mapping
@@ -746,7 +745,7 @@
       throw new QueryException("Invalid query.", e);
     }
 
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all simple constraints.");
 
     // create a mapping of URIs to simple constraint structures
@@ -807,12 +806,12 @@
       // find the URI references and the referred URIs.
       query = interpreter.parseQuery("select $constraint $constraint2 $type from <" + ruleModel +
           "> where $constraint <krule:argument> $constraint2 and $constraint <rdf:type> $type and " +
-          "($type <mulgara:is> <krule:ConstraintConjunction> or $type <mulgara:is> <krule:ConstraintDisjuntion>);");
+          "($type <mulgara:is> <krule:ConstraintConjunction> or $type <mulgara:is> <krule:ConstraintDisjunction>);");
     } catch (Exception e) {
       throw new QueryException("Invalid query.", e);
     }
 
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all join constraints.");
 
     // accumulate all the constraint links and types
@@ -888,7 +887,7 @@
       throw new QueryException("Invalid query.", e);
     }
 
-    Answer answer = session.query(query);
+    Answer answer = query(query);
     logger.debug("Found all having constraints.");
 
     try {
@@ -920,7 +919,7 @@
     } catch (Exception e) {
       throw new QueryException("Invalid query.", e);
     }
-    Answer answer = session.query(query);
+    Answer answer = query(query);
 
     logger.debug("Retrieved all transitive constraints.");
 
@@ -992,6 +991,11 @@
 
     // build the return list
     List<ConstraintExpression> cList = new ArrayList<ConstraintExpression>();
+    // check argument validity
+    if (constraints == null) {
+      logger.warn("Empty constraint found in data. Ignored.");
+      return cList;
+    }
     // go through the arguments
     for (Node cNode: constraints) {
       logger.debug("converting: " + cNode);
@@ -1006,7 +1010,8 @@
         constraintExpr = newJoinConstraint((Node)typeMap.get(cNode), constraintArgs);
       }
       // add the constraint argument to the list
-      cList.add(constraintExpr);
+      if (constraintExpr != null) cList.add(constraintExpr);
+      else logger.warn("Missing constraint expression. Ignoring.");
     }
     return cList;
   }
@@ -1015,12 +1020,14 @@
   /**
    * Create a new join constraint.
    *
-   * @param type The URI for the type to create.
+   * @param type The URI for the type to create. <code>null</code> is a handled error.
    * @param args The list of arguments for the constraint.
-   * @return a new join constraint of the correct type.
+   * @return a new join constraint of the correct type, or <code>null</code> if the type is null.
    */
   private ConstraintExpression newJoinConstraint(Node type, List<ConstraintExpression> args) throws KruleStructureException {
     logger.debug("Building join constraint of type <" + type + ">: " + args);
+    // confirm arguments
+    if (type == null) return null;
 
     if (type.equals(CONSTRAINT_CONJUNCTION)) {
       return new ConstraintConjunction(args);
@@ -1110,4 +1117,19 @@
     }
   }
 
+  /**
+   * Local wrapper for querying on an OperationContext. Since {@link OperationContext#doQuery(Query)}
+   * throws an {@link Exception}, this is captured and wrapped in or cast to a {@link QueryException}.
+   * @param q The query to execute.
+   * @return The Answer to the query.
+   * @throws QueryException If the query fails.
+   */
+  private Answer query(Query q) throws QueryException {
+    try {
+      return operationContext.doQuery(q);
+    } catch (Exception e) {
+      if (e instanceof QueryException) throw (QueryException)e;
+      throw new QueryException("Unable to execute query", e);
+    }
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/QueryStruct.java
===================================================================
--- branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/QueryStruct.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/QueryStruct.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -48,6 +48,7 @@
 import org.mulgara.query.ModelUnion;
 import org.mulgara.query.Order;
 import org.mulgara.query.Query;
+import org.mulgara.query.SelectElement;
 import org.mulgara.query.UnconstrainedAnswer;
 import org.mulgara.query.Variable;
 import org.mulgara.query.VariableFactory;
@@ -76,7 +77,7 @@
   private ConstraintElement[] select = new ConstraintElement[3];
 
   /** List of elements which are variables, or ConstantValues. */
-  private List<Object> variables;
+  private List<SelectElement> variables;
 
   /** The model expresison for the query. */
   private ModelExpression models;
@@ -112,7 +113,7 @@
     VariableFactory variableFactory = new VariableFactoryImpl();
 
     // set up a list of variables
-    variables = new ArrayList<Object>();
+    variables = new ArrayList<SelectElement>();
 
     // convert the parameters to usable objects
     for (int i = 0; i < 3; i++) {
@@ -129,7 +130,7 @@
 
         // get the variable
         select[i] = (Variable)varReferences.get(element);
-        variables.add(select[i]);
+        variables.add((Variable)select[i]);
 
       } else if (types[i].equals(KruleLoader.LITERAL)) {
         

Modified: branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/Rule.java
===================================================================
--- branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/Rule.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/Rule.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,6 @@
 
 // Java 2 standard packages
 import java.io.Serializable;
-import java.net.*;
 import java.util.*;
 
 // Third party packages
@@ -37,7 +36,13 @@
 
 // Locally written packages
 import org.mulgara.query.*;
-import org.mulgara.server.Session;
+import org.mulgara.resolver.OperationContext;
+import org.mulgara.resolver.spi.LocalizedTuples;
+import org.mulgara.resolver.spi.Resolver;
+import org.mulgara.resolver.spi.ResolverException;
+import org.mulgara.resolver.spi.SystemResolver;
+import org.mulgara.resolver.spi.TuplesWrapperStatements;
+import static org.mulgara.krule.RuleStructure.UNINITIALIZED;
 
 /**
  * Represents a single executable rule.
@@ -52,8 +57,8 @@
  */
 public class Rule implements Serializable {
 
-  static final long serialVersionUID = -3762458306756060166L;
-  
+  private static final long serialVersionUID = 3080424724378196982L;
+
   /** Logger.  */
   private static Logger logger = Logger.getLogger(Rule.class.getName());
 
@@ -66,8 +71,8 @@
   /** The query for this rule. This contains the information for the base model. */
   private Query query;
 
-  /** The model containing the inferred data. */
-  private URI targetModel;
+  /** The graph receiving the inferred data. */
+  private long targetGraph = UNINITIALIZED;
 
   /** The most recent size of the data matching this rule. */
   private long lastCount;
@@ -109,12 +114,12 @@
 
 
   /**
-   * Set the target model for the rule.
+   * Set the target graph for the rule.
    *
    * @param target The URI of the model to insert inferences into.
    */
-  public void setTargetModel(URI target) {
-    targetModel = target;
+  public void setTargetGraph(long target) {
+    targetGraph = target;
   }
 
 
@@ -161,36 +166,49 @@
   /**
    * Runs this rule.
    * TODO: count the size of each individual constraint
+   * TODO: Go back to using a Session once they have been properly refactored for transactions
    * 
-   * @param session The session to execute the rule against.
+   * @param context The context to query against.
+   * @param resolver The resolver to add data with.
+   * @param sysResolver The resolver to localize data with.
    */
-  public void execute(Session session) throws QueryException, TuplesException {
+  public void execute(OperationContext context, Resolver resolver, SystemResolver sysResolver) throws QueryException, TuplesException, ResolverException {
+    if (targetGraph == UNINITIALIZED) throw new IllegalStateException("Target graph has not been set");
     // see if this rule needs to be run
-  	Answer answer = session.query(query);
-  	// compare the size of the result data  	
-  	long newCount = answer.getRowCount(); 
-  	if (newCount == lastCount) {
-  	  logger.debug("Rule <" + name + "> is up to date.");
-  	  // this rule does not need to be run
-  	  return;
+  	Answer answer = null;
+  	try {
+    	try {
+        answer = context.doQuery(query);
+      } catch (Exception e) {
+        throw new QueryException("Unable to access data in rule.", e);
+      }
+    	// compare the size of the result data  	
+    	long newCount = answer.getRowCount(); 
+    	if (newCount == lastCount) {
+    	  logger.debug("Rule <" + name + "> is up to date.");
+    	  // this rule does not need to be run
+    	  return;
+    	}
+    	logger.debug("Rule <" + name + "> has increased by " + (newCount - lastCount) + " entries");
+      logger.debug("Inserting results of: " + query);
+      if (answer instanceof AnswerImpl) {
+        AnswerImpl a = (AnswerImpl)answer;
+        String list = "[ ";
+        Variable[] v = a.getVariables();
+        for (int i = 0; i < v.length; i++) {
+          list += v[i] + " ";
+        }
+        list += "]";
+        logger.debug("query has " + a.getNumberOfVariables() + " variables: " + list);
+      }
+    	// insert the resulting data
+      insertData(answer, resolver, sysResolver);
+      // update the count
+      lastCount = newCount;
+      logger.debug("Insertion complete, triggering rules for scheduling.");
+  	} finally {
+  	  answer.close();
   	}
-  	logger.debug("Rule <" + name + "> has increased by " + (newCount - lastCount) + " entries");
-    logger.debug("Inserting results of: " + query);
-    if (answer instanceof AnswerImpl) {
-      AnswerImpl a = (AnswerImpl)answer;
-      String list = "[ ";
-      Variable[] v = a.getVariables();
-      for (int i = 0; i < v.length; i++) {
-        list += v[i] + " ";
-      }
-      list += "]";
-      logger.debug("query has " + a.getNumberOfVariables() + " variables: " + list);
-    }
-  	// insert the resulting data
-  	session.insert(targetModel, query);
-  	// update the count
-  	lastCount = newCount;
-  	logger.debug("Insertion complete, triggering rules for scheduling.");
   	// trigger subsequent rules
   	scheduleTriggeredRules();
   }
@@ -200,7 +218,41 @@
    * Schedule subsequent rules.
    */
   private void scheduleTriggeredRules() {
-  	for (Rule rule: triggerSet) ruleStruct.schedule(rule);
+  	Iterator<Rule> it = triggerSet.iterator();
+  	while (it.hasNext()) ruleStruct.schedule(it.next());
   }
 
+
+  /**
+   * Inserts an Answer into the data store on the current transaction.
+   * @param answer The data to be inserted.
+   * @param resolver The mechanism for adding data in the current transaction.
+   * @param sysResolver Used for localizing the globalized data in the answer parameter.
+   *        TODO: use a localized Tuples instead of Answer when src and dest are on the same server.
+   * @throws TuplesException There was an error localizing the answer.
+   * @throws ResolverException There was an error inserting the data.
+   */
+  private void insertData(Answer answer, Resolver resolver, SystemResolver sysResolver) throws TuplesException, ResolverException {
+    TuplesWrapperStatements statements = convertToStatements(answer, sysResolver);
+    try {
+      resolver.modifyModel(targetGraph, statements, true);
+    } finally {
+      statements.close();
+    }
+  }
+
+
+  /**
+   * Converts an Answer with 3 selection values to a set of statements for insertion.
+   * @param answer The answer to convert.
+   * @param resolver The resolver used for localizing the results, since Answers are globalized.
+   *        TODO: remove this round trip of local->global->local.
+   * @return A set of Statements.
+   * @throws TuplesException The statements could not be instantiated.
+   */
+  private TuplesWrapperStatements convertToStatements(Answer answer, SystemResolver resolver) throws TuplesException {
+    Variable[] vars = answer.getVariables();
+    assert vars.length == 3;
+    return new TuplesWrapperStatements(new LocalizedTuples(resolver, answer, true), vars[0], vars[1], vars[2]);
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/RuleStructure.java
===================================================================
--- branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/RuleStructure.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/krule/java/org/mulgara/krule/RuleStructure.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -39,8 +39,17 @@
 
 import org.apache.log4j.Logger;
 
+import org.mulgara.query.rdf.URIReferenceImpl;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.TuplesException;
+import org.mulgara.resolver.OperationContext;
+import org.mulgara.resolver.spi.LocalizeException;
+import org.mulgara.resolver.spi.Resolver;
+import org.mulgara.resolver.spi.ResolverException;
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.resolver.spi.Statements;
+import org.mulgara.resolver.spi.SystemResolver;
+import org.mulgara.resolver.spi.TripleSetWrapperStatements;
 import org.mulgara.rules.InitializerException;
 import org.mulgara.rules.Rules;
 import org.mulgara.rules.RulesException;
@@ -59,8 +68,11 @@
  */
 public class RuleStructure implements Rules, Serializable {
 
-  static final long serialVersionUID = 452741614702661812L;
+  private static final long serialVersionUID = 7891222973611830607L;
 
+  /** Used to indicate that a gNode is not configured */
+  static final long UNINITIALIZED = -1;
+
   /** Logger.  */
   private static Logger logger = Logger.getLogger(RuleStructure.class.getName());
 
@@ -70,11 +82,11 @@
   /** Map of rule names to the rule. */
   private Map<String,Rule> ruleMap;
 
-  /** The model containing the base data.  Current unused. */
-  private URI baseModel;
+  /** The URI of the target graph to contain the entailments. */
+  private URI targetGraphURI;
 
-  /** The terget model to contain the entailments. */
-  private URI targetModel;
+  /** The target graph to contain the entailments. */
+  private long targetGraph = UNINITIALIZED;
 
   /** The current list of rules that have to be run. */
   private LinkedHashSet<Rule> runQueue;
@@ -181,33 +193,12 @@
 
 
   /**
-   * Set the base model for the rules.
+   * Set the target model for the rules. This will get localized when the rules are run.
    *
-   * @param base The URI of the base data to apply rules to.
+   * @param target The URI of the target graph to insert inferences into.
    */
-  public void setBaseModel(URI base) {
-    baseModel = base;
-  }
-
-
-  /**
-   * Get the base model for the rules.  Currently unused.
-   *
-   * @param base The URI of the base data to apply rules to.
-   */
-  public URI getBaseModel() {
-    return baseModel;
-  }
-
-
-  /**
-   * Set the target model for the rules.
-   *
-   * @param target The URI of the target model to insert inferences into.
-   */
   public void setTargetModel(URI target) {
-    targetModel = target;
-    for (Rule rule: rules) rule.setTargetModel(target);
+    targetGraphURI = target;
   }
 
 
@@ -216,56 +207,46 @@
    * This means that any triggered rules are scheduled for evaluation,
    * and are not run immediately.
    *
-   * @param params the session to use.
+   * @param params An array containing the transactionally controlled {@link OperationContext}
+   *        and {@link SystemResolver} to use. This is not a structured parameter as it will
+   *        eventually drop back to a single {@link Session} parameter like it used to be. 
    */
   public void run(Object params) throws RulesException {
     logger.debug("Run called");
-    if (!(params instanceof Session)) {
-      throw new IllegalArgumentException("Rules must be run with a session");
-    }
-    Session session = (Session)params;
+    validateParams(params);
+    // set up the operating parameters
+    OperationContext context = (OperationContext)((Object[])params)[0];
+    SystemResolver systemResolver = (SystemResolver)((Object[])params)[1];
+
+    // determine the graph to insert into, and the resolver for that graph
+    localizeRuleTarget(context, systemResolver);
+    Resolver resolver = extractTargetResolver(context);
+
     // set up the run queue
     runQueue = new LinkedHashSet<Rule>(rules);
     // fill the run queue
     runQueue.addAll(rules);
     Rule currentRule = null;
     try {
-      // use a single transaction
-      session.setAutoCommit(false);
       // start by inserting the axioms
-      insertAxioms(session);
+      insertAxioms(resolver, systemResolver);
       // process the queue
       while (runQueue.size() > 0) {
         // get the first rule from the queue
         currentRule = popRunQueue();
         logger.debug("Executing rule: " + currentRule);
         // execute the rule
-        currentRule.execute(session);
+        currentRule.execute(context, resolver, systemResolver);
       }
     } catch (TuplesException te) {
       logger.error("Error getting data within rule: " + currentRule);
-      try {
-        session.rollback();
-      } catch (QueryException e) {
-        logger.error("Error during rollback: " + currentRule);
-      }
       throw new RulesException("Error getting data within rule: " + currentRule, te);
+    } catch (ResolverException re) {
+      logger.error("Error inserting data from rule: " + currentRule);
+      throw new RulesException("Error inserting data from rule: " + currentRule, re);
     } catch (QueryException qe) {
       logger.error("Error executing rule: " + currentRule, qe);
-      try {
-        session.rollback();
-      } catch (QueryException e) {
-        logger.error("Error during rollback: " + currentRule);
-      }
       throw new RulesException("Error executing rule: " + currentRule, qe);
-    } finally {
-      try {
-        // this will commit the current phase, or do nothing if we rolled back
-        session.setAutoCommit(true);
-      } catch (QueryException e) {
-        logger.error("Unable to close transaction.", e);
-        throw new RulesException("Unable to close transaction", e);
-      }
     }
     logger.debug("All rules complete");
   }
@@ -302,17 +283,79 @@
   /**
    * Inserts all axioms into the output model in the current session.
    *
-   * @param session The session to use for writing.
+   * @param resolver The resolver to use for writing.
    */
-  private void insertAxioms(Session session) throws QueryException {
+  private void insertAxioms(Resolver resolver, ResolverSession resolverSession) throws QueryException {
     logger.debug("Inserting axioms");
     // check if axioms were provided
     if (axioms == null) {
       logger.debug("No axioms provided");
       return;
     }
-    // insert the statements
-    session.insert(targetModel, axioms);
+    try {
+      // Create the statements
+      Statements stmts = new TripleSetWrapperStatements(axioms, resolverSession, TripleSetWrapperStatements.PERSIST);
+      // insert the statements
+      resolver.modifyModel(targetGraph, stmts, true);
+    } catch (TuplesException te) {
+      throw new QueryException("Unable to convert axioms for storage", te);
+    } catch (ResolverException re) {
+      throw new QueryException("Unable to store axioms", re);
+    }
   }
 
+
+  /**
+   * Calculate the localized gNode for the target graph, and update all rules with this info.
+   * @param context The context to query for the canonical form of the graph.
+   * @param sysResolver The resolver to localize the graph info on.
+   * @throws RulesException If the graph URI could not be localized.
+   */
+  private void localizeRuleTarget(OperationContext context, SystemResolver sysResolver) throws RulesException {
+    try {
+      targetGraph = sysResolver.localize(new URIReferenceImpl(targetGraphURI));
+    } catch (LocalizeException e) {
+      throw new RulesException("Unable to make a determination on the destination graph: " + targetGraphURI, e);
+    }
+    targetGraph = context.getCanonicalModel(targetGraph);
+    // tell the rules which graph they need to modify
+    for (Rule rule: rules) rule.setTargetGraph(targetGraph);
+  }
+
+
+  /**
+   * Determine the resolver to use for modifications to the target graph.
+   * @param context The context to extract the resolver from.
+   * @return A resolver associated with the current transactional context.
+   * @throws RulesException If a resolver could not be obtained.
+   */
+  private Resolver extractTargetResolver(OperationContext context) throws RulesException {
+    if (targetGraph == UNINITIALIZED) throw new IllegalStateException("Target graph has not been resolved");
+    try {
+      return context.obtainResolver(context.findModelResolverFactory(targetGraph));
+    } catch (QueryException e) {
+      throw new RulesException("Unable to get access to modify the target graph: " + targetGraphURI);
+    }
+  }
+
+
+  /**
+   * Confirm that the parameters for {@link #run(Object)} are the expected type, since
+   * they are not subject to static type checking. The complexity of this object will be
+   * reduced when it is replaced by a {@link Session} again.
+   * @param params The parameters to {@link #run(Object)}. For the moment this is a 2 element
+   *        array of Object, with elements of {@link OperationContext} and {@link SystemResolver}.
+   * @throws IllegalArgumentException If the parameters are not of the expected form.
+   */
+  private void validateParams(Object params) {
+    if (!(params instanceof Object[])) {
+      throw new IllegalArgumentException("Rules must be run with parameters of OperationContext/SystemResolver");
+    }
+    if (!(((Object[])params)[0] instanceof OperationContext)) {
+      throw new IllegalArgumentException("Rules must be run with an OperationContext");
+    }
+    if (!(((Object[])params)[1] instanceof SystemResolver)) {
+      throw new IllegalArgumentException("Rules must be run with a SystemResolver");
+    }
+  }
 }

Copied: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/CommandExecutor.java (from rev 722, trunk/src/jar/query/java/org/mulgara/connection/CommandExecutor.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/CommandExecutor.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/CommandExecutor.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,53 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+package org.mulgara.connection;
+
+import org.mulgara.query.Answer;
+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;
+
+
+/**
+ * A central point to direct to commands on a connection.
+ *
+ * @created Feb 22, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2008 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public abstract class CommandExecutor implements Connection {
+
+  /**
+   * @see org.mulgara.connection.Connection#execute(org.mulgara.query.operation.Command)
+   */
+  public String execute(Command cmd) throws Exception {
+    return (String)cmd.execute(this);
+  }
+
+  /**
+   * @see org.mulgara.connection.Connection#execute(org.mulgara.query.operation.Load)
+   */
+  public Long execute(Load cmd) throws QueryException {
+    return (Long)cmd.execute(this);
+  }
+
+  /**
+   * @see org.mulgara.connection.Connection#execute(org.mulgara.query.Query)
+   */
+  public Answer execute(Query cmd) throws QueryException, TuplesException {
+    return (Answer)cmd.execute(this);
+  }
+
+}

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/Connection.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/Connection.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/Connection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -13,12 +13,57 @@
 
 import java.net.URI;
 
+import org.mulgara.query.Answer;
+import org.mulgara.query.Query;
 import org.mulgara.query.QueryException;
+import org.mulgara.query.TuplesException;
 import org.mulgara.server.Session;
+import org.mulgara.query.operation.*;
 
 /**
- * A connection for sending commands to a server.
+ * This class 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.
  *
+ * While Connections can be created with the normal constructor, it may be preferable to use
+ * an instance of {@link org.mulgara.connection.ConnectionFactory} in order to cache connections
+ * based on the server URI.
+ *
+ * {@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 Paul Gearon
  * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
@@ -71,4 +116,29 @@
    * Closes the current connection.
    */
   public void close() throws QueryException;
+
+  // Central execution of Command operations
+
+  /**
+   * Generic command execution method.
+   * @param The command to execute.
+   * @return A status message
+   * @throws Exception A general exception catchall
+   */
+  public String execute(Command cmd) throws Exception;
+
+  /**
+   * 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;
+
 }
\ No newline at end of file

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/DummyConnection.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/DummyConnection.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/DummyConnection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -25,7 +25,7 @@
  * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
  * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
  */
-public class DummyConnection implements Connection {
+public class DummyConnection extends CommandExecutor implements Connection {
 
   /** Logger. */
   private static final Logger logger = Logger.getLogger(DummyConnection.class.getName());

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/SessionConnection.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/SessionConnection.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/connection/SessionConnection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
  * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
  * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
  */
-public class SessionConnection implements Connection {
+public class SessionConnection extends CommandExecutor implements Connection {
 
   /** Logger. */
   private static final Logger logger = Logger.getLogger(SessionConnection.class.getName());

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/parser/Interpreter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/parser/Interpreter.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/parser/Interpreter.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,6 +36,12 @@
   /** The Dublin Core namespace prefix. */
   public static final String DC = "dc";
 
+  /** The Simple Knowledge Organization System namespace prefix. */
+  public static final String SKOS = "skos";
+
+  /** The Friend Of A Friend namespace prefix. */
+  public static final String FOAF = "foaf";
+
   /** The URI of the rdf namespace. */
   public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
 
@@ -54,6 +60,12 @@
   /** The URI of the dc namespace. */
   public static final String DC_NS = "http://purl.org/dc/elements/1.1/";
 
+  /** The URI of the skos namespace. */
+  public static final String SKOS_NS = "http://www.w3.org/2004/02/skos/core#";
+
+  /** The URI of the foaf namespace. */
+  public static final String FOAF_NS = "http://xmlns.com/foaf/0.1/";
+
   /**
   * Parses the given TQL command.
   *

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AggregateFunction.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AggregateFunction.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AggregateFunction.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -49,7 +49,7 @@
  *
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-public abstract class AggregateFunction implements Serializable {
+public abstract class AggregateFunction implements SelectElement, Serializable {
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.mulgara.util.ResultSetRow;
 import org.mulgara.util.TestResultSet;
 
@@ -81,8 +81,7 @@
   /**
    * Logger. This is named after the class.
    */
-  private final static Category logger =
-      Category.getInstance(AnswerImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(AnswerImpl.class);
 
   static {
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperations.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperations.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperations.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.query;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
 * Operations permitted on {@link Answer}s.
@@ -57,8 +57,7 @@
   *
   * This is named after the class.
   */
-  private final static Category logger =
-    Category.getInstance(AnswerOperations.class.getName());
+  private final static Logger logger = Logger.getLogger(AnswerOperations.class);
 
   /**
   * Equality is by value, with both row and column order significant.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperationsUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperationsUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerOperationsUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.util.MulgaraResultSet;
@@ -65,8 +65,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(AnswerOperationsUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(AnswerOperationsUnitTest.class);
 
   /**
    * Test instance.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/AnswerUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import java.util.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.util.MulgaraResultSet;
@@ -66,7 +66,7 @@
   /**
    * Logger.
    */
-  private Category logger = Category.getInstance(AnswerUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(AnswerUnitTest.class);
 
   /**
    * Test instance.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstantValue.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstantValue.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstantValue.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -48,7 +48,7 @@
  *
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-public class ConstantValue implements Serializable {
+public class ConstantValue implements SelectElement, Serializable {
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintHaving.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintHaving.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintHaving.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 import org.jrdf.graph.*;
 
 
@@ -61,7 +61,7 @@
 public abstract class ConstraintHaving extends AbstractConstraintExpression implements Constraint {
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintHaving.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintHaving.class);
 
   /**
     * The 4-tuple of elements (either nodes or variables)

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 /**
  * A constraint. The elements within the constraint can be either variables or
@@ -67,7 +67,7 @@
   static final long serialVersionUID = -3127160729187334757L;
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintImpl.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintImpl.class);
 
   /**
    * The 4-tuple of elements (either nodes or variables)

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintIs.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintIs.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintIs.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -65,7 +65,7 @@
   private static final long serialVersionUID = 7952821738407976852L;
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintIs.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintIs.class);
 
   /** Create the predicate to be used to indicate equality. */
   public static final URIReferenceImpl MULGARA_IS = new URIReferenceImpl(SpecialPredicates.MULGARA_IS);

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintNotOccurs.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintNotOccurs.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintNotOccurs.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.query;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -57,7 +57,7 @@
 public class ConstraintNotOccurs extends ConstraintHaving {
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintOccurs.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintOccurs.class);
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccurs.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccurs.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccurs.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.query;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -57,7 +57,7 @@
 public class ConstraintOccurs extends ConstraintHaving {
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintOccurs.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintOccurs.class);
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursLessThan.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursLessThan.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursLessThan.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.query;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -57,7 +57,7 @@
 public class ConstraintOccursLessThan extends ConstraintHaving {
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintOccursLessThan.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintOccursLessThan.class);
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursMoreThan.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursMoreThan.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOccursMoreThan.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.query;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -57,7 +57,7 @@
 public class ConstraintOccursMoreThan extends ConstraintHaving {
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(ConstraintOccursMoreThan.class.getName());
+  // private final static Logger logger = Logger.getLogger(ConstraintOccursMoreThan.class);
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ConstraintOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 /**
  * A constraint expression composed of two subexpressions and a dyadic operator.
@@ -65,7 +65,7 @@
   static final long serialVersionUID = -236847137057853871L;
 
   // /** Logger. */
-  // private static Category logger = Category.getInstance(ConstraintOperation.class.getName());
+  // private static Logger logger = Logger.getLogger(ConstraintOperation.class);
 
   //
   // Constructor

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelLiteral.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelLiteral.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import javax.xml.transform.stream.StreamResult;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.xml.sax.InputSource;
 
 /**
@@ -70,8 +70,7 @@
   /**
    * Logger. This is named after the class.
    */
-  private final static Category logger =
-      Category.getInstance(ModelLiteral.class.getName());
+  private final static Logger logger = Logger.getLogger(ModelLiteral.class);
 
   /**
    * The content of the model, an RDF syntax byte sequence.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelPartition.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelPartition.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelPartition.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
 
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * A model expression composed of the union of two subexpressions.
@@ -65,8 +65,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-    Category.getInstance(ModelPartition.class.getName());
+  private final static Logger logger = Logger.getLogger(ModelPartition.class);
 
   //
   // Constructor

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResource.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResource.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -104,15 +104,16 @@
 
   /**
    * @return an immutable singleton {@link Set} containing the {@link URL} of
-   *   the server if this is a Java RMI or BEEP model, or the empty {@link Set}
-   *   otherwise
+   *   the server if this is a Java RMI, BEEP, or local model, or the empty
+   *   {@link Set} otherwise
    */
   @SuppressWarnings("unchecked")
   public Set<URI> getDatabaseURIs() {
 
     try {
 
-      if ("beep".equals(uri.getScheme()) || "rmi".equals(uri.getScheme())) {
+      if ("beep".equals(uri.getScheme()) || "rmi".equals(uri.getScheme()) ||
+          "local".equals(uri.getScheme())) {
 
         // In Java RMI models, the database is the URI without
         // the fragment identifier

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResourceUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResourceUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/ModelResourceUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 import junit.framework.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Tests the functionality of ModelResource.
@@ -59,8 +59,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(ModelResourceUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(ModelResourceUnitTest.class);
 
   /**
    * Construct a new unit test.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Query.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Query.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Query.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *   Move to java-generics copyright Netymon Pty Ltd
  *
  * [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
@@ -72,13 +73,13 @@
    * that there is no <code>select</code> clause and that no projection will be
    * performed.
    */
-  private List<Object> variableList;
+  private List<SelectElement> variableList;
 
   /**
    * Mutable version of the variable list. This isn't exposed via {@link
    * #getVariableList} the way {@link #variableList} is.
    */
-  private List<Object> mutableVariableList;
+  private List<SelectElement> mutableVariableList;
 
   /** The model expression. It corresponds to the <code>from</code> clause. */
   private ModelExpression modelExpression;
@@ -142,7 +143,7 @@
    *     <var>constraintExpression</var>, <var>orderList<var> or
    *     <var>answer</var> are <code>null</code>
    */
-  public Query(List<Object> variableList, ModelExpression modelExpression,
+  public Query(List<? extends SelectElement> variableList, ModelExpression modelExpression,
       ConstraintExpression constraintExpression,
       ConstraintHaving havingExpression, List<Order> orderList, Integer limit,
       int offset, Answer answer) {
@@ -177,7 +178,7 @@
     }
 
     // Initialize fields
-    this.mutableVariableList = (variableList == null) ? null : new ArrayList<Object>(variableList);
+    this.mutableVariableList = (variableList == null) ? null : new ArrayList<SelectElement>(variableList);
     this.variableList = (variableList == null) ? null : Collections.unmodifiableList(mutableVariableList);
     this.modelExpression = modelExpression;
     this.constraintExpression = constraintExpression;
@@ -233,10 +234,8 @@
       cloned.mutableVariableList = null;
       cloned.variableList = null;
     } else {
-      cloned.variableList = new ArrayList<Object>();
-      Iterator<Object> i = variableList.iterator();
-      while (i.hasNext()) {
-        Object o = i.next();
+      cloned.variableList = new ArrayList<SelectElement>();
+      for (SelectElement o : variableList) {
         if (o instanceof Subquery) {
           Subquery s = (Subquery)o;
           cloned.variableList.add(new Subquery(s.getVariable(), (Query)s.getQuery().clone()));
@@ -270,7 +269,7 @@
    * @return a {@link List} containing one or more {@link Variable}s, {@link ContantValue}s,
    * {@link Count}s or {@link Subquery}
    */
-  public List<Object> getVariableList() {
+  public List<SelectElement> getVariableList() {
     return variableList;
   }
 
@@ -407,8 +406,10 @@
     answer = null;
 
     if (mutableVariableList != null) {
-      for (Object v: mutableVariableList) {
-        if (v instanceof AggregateFunction) ((AggregateFunction)v).getQuery().close();
+      for (SelectElement v: mutableVariableList) {
+        if (v instanceof AggregateFunction) {
+          ((AggregateFunction)v).getQuery().close();
+        }
       }
     }
   }

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/QueryUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/QueryUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/QueryUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // Log4J
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 // Locally written packages.
 import org.mulgara.query.rdf.LiteralImpl;
@@ -45,18 +45,8 @@
  * Purpose: Test case for {@link Query}.
  *
  * @created 2001-10-23
- *
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
- * @version $Revision: 1.8 $
- *
- * @modified $Date: 2005/01/05 04:58:20 $ by $Author: newmana $
- *
- * @maintenanceAuthor $Author: newmana $
- *
- * @copyright &copy;2001-2004
- *   <a href="http://www.pisoftware.com/">Plugged In Software Pty Ltd</a>
- *
+ * @copyright &copy;2001-2004 <a href="http://www.pisoftware.com/">Plugged In Software Pty Ltd</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 public class QueryUnitTest extends TestCase {
@@ -67,7 +57,7 @@
   private Query query;
 
   // /** Logger. */
-  // private Category logger = Category.getInstance(QueryUnitTest.class.getName());
+  // private static final Logger logger = Logger.getLogger(QueryUnitTest.class);
 
   /**
    * Constructs a new answer test with the given name.
@@ -84,7 +74,6 @@
    * @return The test suite
    */
   public static Test suite() {
-
     TestSuite suite = new TestSuite();
 
     suite.addTest(new QueryUnitTest("test1Equals"));
@@ -100,7 +89,6 @@
    * @param args the command line arguments
    */
   public static void main(String[] args) {
-
     junit.textui.TestRunner.run(suite());
   }
 
@@ -111,9 +99,8 @@
    */
   @SuppressWarnings("unchecked")
   public void setUp() throws Exception {
-
     query = new Query(
-        Arrays.asList(new Object[] {new Variable("x")}), // variable list
+        Arrays.asList(new SelectElement[] { new Variable("x") }), // variable list
         new ModelResource(new URI("x:m")),      // model expression
         new ConstraintImpl(new Variable("x"),   // constraint expression
         new URIReferenceImpl(new URI("x:p")),
@@ -135,7 +122,6 @@
    * @throws Exception if query fails when it should have succeeded
    */
   public void testClone() throws Exception {
-
     Query copied = (Query) query.clone();
     assertTrue(copied != query);
     assertEquals(copied, query);
@@ -147,9 +133,7 @@
    * @throws Exception if query fails when it should have succeeded
    */
   public void test1Equals() throws Exception {
-
     Query query2 = query;
-
     assertTrue(query.equals(query2));
   }
 
@@ -160,16 +144,15 @@
    */
   @SuppressWarnings("unchecked")
   public void test2Equals() throws Exception {
-
     // Compose test instances
     Query query2 = new Query(
-        Arrays.asList(new Object[] {new Variable("x")}),                    // variable list
+        Arrays.asList(new SelectElement[] { new Variable("x") }), // variable list
         new ModelResource(new URI("x:m")),      // model expression
         new ConstraintImpl(new Variable("x"),   // constraint expression
         new URIReferenceImpl(new URI("x:p")),
         new LiteralImpl("o")),
         null,                                  // no having
-        (List<Order>)Collections.EMPTY_LIST,                // no ordering
+        (List<Order>)Collections.EMPTY_LIST,   // no ordering
         null,                                  // no limit
         0,                                     // zero offset
         new UnconstrainedAnswer());
@@ -186,7 +169,6 @@
    * @throws Exception if query fails when it should have succeeded
    */
   public void test3Equals() throws Exception {
-
     assertTrue(!query.equals(null));
   }
 }

Copied: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SelectElement.java (from rev 722, trunk/src/jar/query/java/org/mulgara/query/SelectElement.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SelectElement.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SelectElement.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.query;
+
+import java.io.Serializable;
+
+/**
+ * Marker interface to identify elements legally permitted within the
+ * select-clause of an itql query.
+ *
+ * @created 2008-01-14
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ * @copyright &copy;2008 <a href="http://www.topazproject.org/">The Topaz Foundation</a>
+ * @licence Apache License v2.0
+ */
+public interface SelectElement extends Serializable, Cloneable { }

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SingleTransitiveConstraint.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SingleTransitiveConstraint.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/SingleTransitiveConstraint.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 /**
  * A transitive constraint. The elements within the constraint must be variable
@@ -69,7 +69,7 @@
   static final long serialVersionUID = -3828723182891026790L;
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(Constraint.class.getName());
+  // private final static Logger logger = Logger.getLogger(Constraint.class);
 
   /**
    * The constraint containing the transitive predicate.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/TransitiveConstraint.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/TransitiveConstraint.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/TransitiveConstraint.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 /**
  * A transitive constraint.  The constraint must take the form of an anchored
@@ -69,7 +69,7 @@
   static final long serialVersionUID = -3828723182891026790L;
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(Constraint.class.getName());
+  // private final static Logger logger = Logger.getLogger(Constraint.class);
 
   /**
    * The constraint containing the anchored transitive predicate.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/UnconstrainedAnswer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/UnconstrainedAnswer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/UnconstrainedAnswer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.Serializable;
 
 // Third party packages
-import org.apache.log4j.Category;  // Apache Log4J
+import org.apache.log4j.Logger;  // Apache Log4J
 
 /**
  * An {@link Answer} which is true no matter what value any variable takes.
@@ -68,8 +68,7 @@
    *
    * This is named after the class.
    */
-  private static final Category logger =
-      Category.getInstance(UnconstrainedAnswer.class.getName());
+  private static final Logger logger = Logger.getLogger(UnconstrainedAnswer.class);
 
   /**
    * The current row number.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Variable.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Variable.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/Variable.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -40,7 +40,7 @@
  *
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-public class Variable implements ConstraintElement {
+public class Variable implements SelectElement, ConstraintElement {
 
   /**
    * Allow newer compiled version of the stub to operate when changes

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/WalkConstraint.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/WalkConstraint.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/WalkConstraint.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-// import org.apache.log4j.Category;
+// import org.apache.log4j.Logger;
 
 /**
  * A walk constraint. The constraint must take the form of an anchored
@@ -68,7 +68,7 @@
   static final long serialVersionUID = 1054509776341736706L;
 
   // /** Logger. */
-  // private final static Category logger = Category.getInstance(Constraint.class.getName());
+  // private final static Logger logger = Logger.getLogger(Constraint.class);
 
   /**
    * The constraint containing the anchored constraint.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/AddAlias.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/AddAlias.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/AddAlias.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -68,7 +68,7 @@
    * @param conn ignored.
    * @return The text of the help request.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return setResultMessage(SUCCESS_MSG_PREFIX + aliasTarget + SUCCESS_MSG_AS + aliasPrefix);
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Backup.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Backup.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Backup.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -62,7 +62,7 @@
   /**
    * @return The URI of the destination graph.
    */
-  public URI getServerURI() throws UnsupportedOperationException {
+  public URI getServerURI() {
     return serverUri;
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Command.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Command.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Command.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -49,10 +49,10 @@
   /**
    * Gets the associated server for a non-local operation.
    * @return the server URI if one can be determined,
-   *  or <code>null</code> if not a valid operation.
-   * @throws UnsupportedOperationException If this command is local only.
+   *  or <code>null</code> if this command is local or the uri
+   *  is unknown for some other reason.
    */
-  URI getServerURI() throws UnsupportedOperationException;
+  URI getServerURI();
 
   /**
    * Executes the operation. This is highly specific to each operation.

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/CreateGraph.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/CreateGraph.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/CreateGraph.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -15,7 +15,9 @@
 
 import org.apache.log4j.Logger;
 import org.mulgara.connection.Connection;
+import org.mulgara.query.QueryException;
 
+
 /**
  * Represents a command to create a new graph.
  * @created Aug 10, 2007
@@ -33,7 +35,12 @@
   
   /** The URI for the type of the graph. */
   private final URI type;
-  
+
+  /**
+   * Create a new create graph command
+   * @param graphUri The identifier for the graph
+   * @param type The identifier for the graph type
+   */
   public CreateGraph(URI graphUri, URI type) {
     super(graphUri);
     this.graphUri = graphUri;
@@ -41,6 +48,16 @@
   }
   
   /**
+   * Create a new create graph command, using the default graph type.
+   * @param graphUri The identifier for the graph
+   */
+  public CreateGraph(URI graphUri) {
+    super(graphUri);
+    this.graphUri = graphUri;
+    this.type = null;
+  }
+  
+  /**
    * Get the URI of the graph to create.
    * @return the URI of the graph to create.
    */
@@ -61,10 +78,10 @@
    * @param The connection to a session to create the graph in.
    * @return Text describing the outcome.
    */
-  public Object execute(Connection conn) throws Exception {
-    if (logger.isDebugEnabled()) logger.debug("Creating new model " + graphUri);
+  public Object execute(Connection conn) throws QueryException {
+    if (logger.isDebugEnabled()) logger.debug("Creating new graph " + graphUri);
     conn.getSession().createModel(graphUri, type);
-    return setResultMessage("Successfully created model " + graphUri);
+    return setResultMessage("Successfully created graph " + graphUri);
   }
 
 }

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Deletion.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Deletion.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Deletion.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -17,6 +17,7 @@
 import org.jrdf.graph.Triple;
 import org.mulgara.connection.Connection;
 import org.mulgara.query.Query;
+import org.mulgara.query.QueryException;
 
 /**
  * An AST element for deleting from a graph.
@@ -50,7 +51,7 @@
    * @param conn the session to delete the data from the graph in.
    * @return Text describing the action.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) throws QueryException {
     if (isSelectBased()) conn.getSession().delete(graph, getSelectQuery());
     else conn.getSession().delete(graph, getStatements());
     return setResultMessage("Successfully deleted statements from " + graph);

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/DropGraph.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/DropGraph.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/DropGraph.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -14,6 +14,7 @@
 import java.net.URI;
 
 import org.mulgara.connection.Connection;
+import org.mulgara.query.QueryException;
 
 /**
  * Represents a command to drop a graph.
@@ -45,9 +46,9 @@
    * @param conn the session to delete the graph in.
    * @return Text describing the action.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) throws QueryException {
     conn.getSession().removeModel(graphUri);
-    return setResultMessage("Successfully dropped model " + graphUri);
+    return setResultMessage("Successfully dropped graph " + graphUri);
   }
 
 }

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Help.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Help.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Help.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -53,7 +53,7 @@
    * @param conn ignored.
    * @return The text of the help request.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return setResultMessage(helpText);
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Insertion.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Insertion.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Insertion.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -18,6 +18,7 @@
 import org.jrdf.graph.Triple;
 import org.mulgara.connection.Connection;
 import org.mulgara.query.Query;
+import org.mulgara.query.QueryException;
 
 /**
  * An AST element for inserting into a graph.
@@ -60,7 +61,7 @@
    * @param conn the session for the graph to insert the data into.
    * @return Text describing the action.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) throws QueryException {
     if (isSelectBased()) conn.getSession().insert(graph, getSelectQuery());
     else conn.getSession().insert(graph, getStatements());
     return setResultMessage("Successfully inserted statements into " + graph);

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Load.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Load.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Load.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -53,7 +53,7 @@
    * @param conn The connection to load the data over.
    * @return The number of statements that were inserted.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) throws QueryException {
     URI src = getSource();
     URI dest = getDestination();
     try {

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/LocalCommand.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/LocalCommand.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/LocalCommand.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -63,9 +63,9 @@
 
   /**
    * Gets the associated server for a non-local operation.
-   * @throws UnsupportedOperationException Always thrown for local commands.
+   * @return <code>null</code>
    */
-  public URI getServerURI() throws UnsupportedOperationException {
+  public URI getServerURI() {
     return null;
   }
   

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/NullOp.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/NullOp.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/NullOp.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
   /**
    * Do nothing.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return null;
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Quit.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Quit.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Quit.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -39,7 +39,7 @@
    * No specific action to be taken here.  The client needs to know that this message
    * requires exiting of the main process.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return finalMessage;
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Restore.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Restore.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/Restore.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -45,7 +45,7 @@
    * @param conn The connection to restore the data over.
    * @return A text string describing the operation.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) throws QueryException {
     URI src = getSource();
     URI dest = getDestination();
     try {

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetTime.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetTime.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetTime.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
   /**
    * Does nothing at the client, except to indicate that time keeping records are required.
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return setResultMessage(SET_TIME + (isOn() ? ON : OFF));
   }
 }

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetUser.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetUser.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/operation/SetUser.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -90,7 +90,7 @@
   /**
    * Does nothing at the client, except to indicate that a user record has been created
    */
-  public Object execute(Connection conn) throws Exception {
+  public Object execute(Connection conn) {
     return setResultMessage(MESSAGE);
   }
 

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/rdf/LiteralImplUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/rdf/LiteralImplUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/rdf/LiteralImplUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 
 // Third party packages
 import junit.framework.*;          // JUnit
-import org.apache.log4j.Category;  // Log4J
+import org.apache.log4j.Logger;    // Log4J
 
 /**
  * Test case for {@link LiteralImpl}.
@@ -62,8 +62,7 @@
    *
    * This is named after the class.
    */
-  private Category logger =
-      Category.getInstance(LiteralImplUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(LiteralImplUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Copied: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/ResourceManagerInstanceAdaptor.java (from rev 722, trunk/src/jar/query/java/org/mulgara/server/ResourceManagerInstanceAdaptor.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/ResourceManagerInstanceAdaptor.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/ResourceManagerInstanceAdaptor.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.server;
+
+
+// Java 2 Standard Packages
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.transaction.xa.XAResource;
+
+/**
+ * Interface to identify a Resource Manager through an XAResource.
+ *
+ * @created 2008-01-14
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ * @copyright &copy;2008 <a href="http://www.topazproject.org/">The Topaz Foundation</a>
+ * @licence Apache License v2.0
+ */
+public interface ResourceManagerInstanceAdaptor {
+  /**
+   * Returns an object that globally identifies a ResourceManagerInstance.
+   * Returned object must override equals/hashcode to compare equal by value.
+   */
+  public Serializable getRMId();
+}

Modified: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/Session.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/Session.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/server/Session.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *    XAResource addition copyright 2008 The Topaz Foundation
  *
  * [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
@@ -32,6 +33,7 @@
 import java.net.*;
 import java.util.*;
 import java.io.*;
+import javax.transaction.xa.XAResource;
 
 // Locally written packages
 import org.jrdf.graph.Triple;
@@ -42,7 +44,6 @@
 import org.mulgara.query.rdf.Mulgara;
 import org.mulgara.rules.InitializerException;
 import org.mulgara.rules.Rules;  // Required only for Javadoc
-import org.mulgara.rules.RulesException;
 import org.mulgara.rules.RulesRef;
 
 /**
@@ -79,7 +80,7 @@
    * @param statements The Set of statements to insert into the model.
    * @throws QueryException if the insert cannot be completed.
    */
-  public void insert(URI modelURI, Set<Triple> statements) throws QueryException;
+  public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException;
 
   /**
    * Insert statements from the results of a query into another model.
@@ -97,7 +98,7 @@
    * @param statements The Set of statements to delete from the model.
    * @throws QueryException if the deletion cannot be completed.
    */
-  public void delete(URI modelURI, Set<Triple> statements) throws QueryException;
+  public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException;
 
   /**
    * Delete statements from a model using the results of query.
@@ -239,15 +240,16 @@
    * @throws InitializerException If there was a problem accessing the rule loading module.
    * @throws QueryException If there was a problem loading the rule structure.
    */
-  public RulesRef buildRules(URI ruleModel, URI baseModel, URI destModel) throws QueryException, org.mulgara.rules.InitializerException, java.rmi.RemoteException;
+  public RulesRef buildRules(URI ruleModel, URI baseModel, URI destModel) throws QueryException, org.mulgara.rules.InitializerException;
 
   /**
    * Rules a set of {@link Rules} on its defined model.
    *
    * @param rules The rules to be run.
-   * @throws RulesException An error was encountered executing the rules.
+   * @throws QueryException An error was encountered executing the rules.
+   * @throws QueryException An error was encountered accessing the rules accross a network.
    */
-  public void applyRules(RulesRef rules) throws RulesException, java.rmi.RemoteException;
+  public void applyRules(RulesRef rules) throws QueryException;
 
   /**
    * Sets whether permanent changes made to the database in this session
@@ -304,4 +306,30 @@
    */
   public void login(URI securityDomain, String username, char[] password);
 
+  /**
+   * Obtain an XAResource for this Session.
+   *
+   * Use of this method is incompatible with any use of implicit or internally
+   * mediated transactions with this Session.
+   * Transactions initiated from the XAResource returned by the read-only
+   * version of this method will be read-only.
+   */
+  public XAResource getXAResource() throws QueryException;
+  public XAResource getReadOnlyXAResource() throws QueryException;
+
+  /**
+   * This class is just a devious way to get static initialization for the
+   * {@link Session} interface.
+   */
+  abstract class ConstantFactory {
+
+    static URI getMulgaraModelURI() {
+      try {
+        return new URI(Mulgara.NAMESPACE + "Model");
+      }
+       catch (URISyntaxException e) {
+        throw new Error("Bad hardcoded URI");
+      }
+    }
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/rdql/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/rdql/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/rdql/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -159,7 +159,7 @@
       <zipfileset src="${lib.dir}/beepcore-0.9.08.jar" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/jargs-0.2.jar" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jrdf.jar}" excludes="META-INF/**"/>
-      <zipfileset src="${lib.dir}/log4j-1.2.8.jar" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/log4j-1.2.15.jar" excludes="META-INF/**"/>
     </jar>
   </target>
 

Modified: branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlOptionParser.java
===================================================================
--- branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlOptionParser.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlOptionParser.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import jargs.gnu.CmdLineParser;
 
 // third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Command line option parser for the iTQL interpreter.
@@ -114,8 +114,7 @@
   /**
    * the category to log to
    */
-  private final static Category log =
-      Category.getInstance(RdqlOptionParser.class.getName());
+  private final static Logger log = Logger.getLogger(RdqlOptionParser.class);
 
   //
   // members

Modified: branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/rdql/java/org/mulgara/rdql/RdqlSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 
 // Third party packages
 import org.apache.log4j.BasicConfigurator;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.log4j.xml.DOMConfigurator;
 
 // Automatically generated packages (SableCC)
@@ -109,8 +109,7 @@
   /**
    * the logging category to log to
    */
-  private final static Category log =
-      Category.getInstance(RdqlSession.class.getName());
+  private final static Logger log = Logger.getLogger(RdqlSession.class);
 
   /**
    * the default path to the pre-loading script

Modified: branches/mgr-61-sparql/src/jar/resolver/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,6 +32,7 @@
     <fileset file="${resolver-jar.dist.dir}/${resolver-jar.jar}"/>
     <fileset file="${resolver-url.dist.dir}/${resolver-url.jar}"/>
     <fileset file="${content-rdfxml.dist.dir}/${content-rdfxml.jar}"/>
+    <fileset file="${driver.dist.dir}/${driver.jar}"/>
   </path>
 
   <path id="resolver-test-classpath">
@@ -81,7 +82,7 @@
           depends="-resolver-prepare, resolver-spi-jar, rules-jar,
                    resolver-http-jar, resolver-file-jar, resolver-url-jar,
                    resolver-jar-jar, content-rdfxml-jar, content-rdfxml-jar,
-                   client-jrdf-jar, jrdf-jar, resolver-xsd-jar"
+                   client-jrdf-jar, jrdf-jar, resolver-xsd-jar, driver-jar"
           description="Compiles all resolver related files included generated
                        source code">
 
@@ -128,14 +129,21 @@
                    resolver-jar, resolver-memory-jar, resolver-xsd-jar,
                    store-nodepool-xa-jar, store-stringpool-xa-jar, resolver-store-jar,
                    resolver-url-jar, store-stringpool-memory-jar, tuples-hybrid-jar,
-                   util-jar, util-xa-jar">
+                   util-jar, util-xa-jar, driver-jar">
 
+
     <antcall target="component-test">
 
       <param name="classpath.id" value="resolver-test-classpath"/>
       <param name="dir" value="${resolver.src.dir}"/>
       <param name="jar" value="${resolver.jar}"/>
     </antcall>
+
+    <antcall target="standalone-test">
+      <param name="classpath.id" value="resolver-test-classpath"/>
+      <param name="dir" value="${resolver.src.dir}"/>
+      <param name="jar" value="${resolver.jar}"/>
+    </antcall>
   </target>
 
   <target name="resolver-javadoc"

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/AdvDatabaseSessionUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/AdvDatabaseSessionUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/AdvDatabaseSessionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,21 +34,45 @@
 import java.io.StringWriter;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
-// Third party packages
-import junit.framework.*;        // JUnit
-import org.apache.log4j.Logger;  // Log4J
-import org.jrdf.graph.SubjectNode;  // JRDF
-import org.jrdf.graph.PredicateNode;  // JRDF
-import org.jrdf.graph.ObjectNode;  // JRDF
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+import org.jrdf.graph.BlankNode;
+import org.jrdf.graph.Literal;
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
 import org.jrdf.graph.Triple;
-
-// Locally written packages
-import org.mulgara.query.*;
+import org.jrdf.graph.URIReference;
+import org.mulgara.query.Answer;
+import org.mulgara.query.ConstraintConjunction;
+import org.mulgara.query.ConstraintDisjunction;
+import org.mulgara.query.ConstraintExpression;
+import org.mulgara.query.ConstraintImpl;
+import org.mulgara.query.ConstraintIs;
+import org.mulgara.query.ModelResource;
+import org.mulgara.query.Order;
+import org.mulgara.query.Query;
+import org.mulgara.query.QueryException;
+import org.mulgara.query.SelectElement;
+import org.mulgara.query.Subquery;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.UnconstrainedAnswer;
+import org.mulgara.query.Variable;
+import org.mulgara.query.rdf.LiteralImpl;
 import org.mulgara.query.rdf.Mulgara;
+import org.mulgara.query.rdf.TripleImpl;
 import org.mulgara.query.rdf.URIReferenceImpl;
-import org.mulgara.query.rdf.TripleImpl;
+import org.mulgara.query.rdf.VariableNodeImpl;
 import org.mulgara.server.Session;
 import org.mulgara.util.FileUtil;
 
@@ -102,6 +126,7 @@
     suite.addTest(new AdvDatabaseSessionUnitTest("testPrefixingWithUnbound"));
     suite.addTest(new AdvDatabaseSessionUnitTest("testDatabaseDelete"));
     suite.addTest(new AdvDatabaseSessionUnitTest("testCreateModel"));
+    suite.addTest(new AdvDatabaseSessionUnitTest("testInsertionBlankNodes"));
 
     return suite;
   }
@@ -219,7 +244,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);
@@ -277,7 +302,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);
@@ -337,10 +362,10 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(new Subquery(new Variable("k0"), new Query(
-          Collections.singletonList((Object)objectVariable),
+          Collections.singletonList(objectVariable),
           new ModelResource(modelURI),                      // FROM
           new ConstraintImpl(subjectVariable,               // WHERE
                          predicateVariable,
@@ -412,10 +437,10 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(new Subquery(new Variable("k0"), new Query(
-          Collections.singletonList((Object)objectVariable),
+          Collections.singletonList(objectVariable),
           new ModelResource(modelURI),                      // FROM
           new ConstraintImpl(subjectVariable,               // WHERE
                          predicateVariable,
@@ -501,7 +526,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);
@@ -588,7 +613,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);
@@ -664,7 +689,7 @@
           Variable predicateVariable = new Variable("predicate");
           Variable objectVariable    = new Variable("object");
 
-          List<Object> selectList = new ArrayList<Object>(3);
+          List<SelectElement> selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -692,7 +717,7 @@
 
           session1.setAutoCommit(true);
 
-          selectList = new ArrayList<Object>(3);
+          selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -761,7 +786,7 @@
           Variable predicateVariable = new Variable("predicate");
           Variable objectVariable    = new Variable("object");
 
-          List<Object> selectList = new ArrayList<Object>(3);
+          List<SelectElement> selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -790,7 +815,7 @@
           session1.rollback();
           session1.setAutoCommit(true);
 
-          selectList = new ArrayList<Object>(3);
+          selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -845,7 +870,7 @@
           Variable predicateVariable = new Variable("predicate");
           Variable objectVariable    = new Variable("object");
 
-          List<Object> selectList = new ArrayList<Object>(3);
+          List<SelectElement> selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -873,7 +898,7 @@
 
           session1.commit();
 
-          selectList = new ArrayList<Object>(3);
+          selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -916,7 +941,7 @@
           session1.removeModel(model3URI);
           session1.createModel(model3URI, null);
 
-          selectList = new ArrayList<Object>(3);
+          selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -958,7 +983,7 @@
 
           session1.setAutoCommit(true);
 
-          selectList = new ArrayList<Object>(3);
+          selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -1011,7 +1036,7 @@
           Variable predicateVariable = new Variable("predicate");
           Variable objectVariable    = new Variable("object");
 
-          List<Object> selectList = new ArrayList<Object>(3);
+          List<SelectElement> selectList = new ArrayList<SelectElement>(3);
           selectList.add(subjectVariable);
           selectList.add(predicateVariable);
           selectList.add(objectVariable);
@@ -1096,7 +1121,73 @@
     }
   }
 
+  /**
+   * Test two insertions in the same transaction using the same variable name.
+   * The variable blank node should map to different internal node ID's in each
+   * insert operation.
+   */
+  public void testInsertionBlankNodes()
+  {
+    logger.info("testInsertionBlankNodes");
+    
+    try {
+      Session session = database.newSession();
+      try {
+        session.createModel(model2URI, null);
+        session.setAutoCommit(false);
+        
+        URIReference refA = new URIReferenceImpl(URI.create("test:a"));
+        URIReference refP1 = new URIReferenceImpl(URI.create("test:p1"));
+        URIReference refP2 = new URIReferenceImpl(URI.create("test:p2"));
+        Literal o1 = new LiteralImpl("o1");
+        Literal o2 = new LiteralImpl("o2");
+        BlankNode bn = new VariableNodeImpl("bn");
+        
+        Set<Triple> insert1 = new HashSet<Triple>();
+        insert1.add(new TripleImpl(refA, refP1, bn));
+        insert1.add(new TripleImpl(bn, refP2, o1));
+        
+        Set<Triple> insert2 = new HashSet<Triple>();
+        insert2.add(new TripleImpl(refA, refP1, bn));
+        insert2.add(new TripleImpl(bn, refP2, o2));
+        
+        session.insert(model2URI, insert1);
+        session.insert(model2URI, insert2);
+        session.setAutoCommit(true);
+        
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
 
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+        
+        Answer answer = session.query(new Query(
+              selectList,                                       // SELECT
+              new ModelResource(model2URI),                     // FROM
+              new ConstraintImpl(subjectVariable,               // WHERE
+                             predicateVariable,
+                             objectVariable),
+              null,                                             // HAVING
+              new ArrayList<Order>(),                           // ORDER BY
+              null,                                             // LIMIT
+              0,                                                // OFFSET
+              new UnconstrainedAnswer()                         // GIVEN
+            ));
+        
+        assertEquals(4, answer.getRowCount());
+      }
+      finally {
+        session.close();
+      }
+    }
+    catch (Exception e) {
+      fail(e);
+    }
+  }
+
   /**
    * Test two simultaneous, explicit transactions, in two threads. The second one should block
    * until the first one sets auto-commit back to true.
@@ -1130,7 +1221,7 @@
                 Variable predicateVariable = new Variable("predicate");
                 Variable objectVariable    = new Variable("object");
 
-                List<Object> selectList = new ArrayList<Object>(3);
+                List<SelectElement> selectList = new ArrayList<SelectElement>(3);
                 selectList.add(subjectVariable);
                 selectList.add(predicateVariable);
                 selectList.add(objectVariable);
@@ -1252,7 +1343,7 @@
                 Variable predicateVariable = new Variable("predicate");
                 Variable objectVariable    = new Variable("object");
 
-                List<Object> selectList = new ArrayList<Object>(3);
+                List<SelectElement> selectList = new ArrayList<SelectElement>(3);
                 selectList.add(subjectVariable);
                 selectList.add(predicateVariable);
                 selectList.add(objectVariable);
@@ -1308,7 +1399,7 @@
                 Variable predicateVariable = new Variable("predicate");
                 Variable objectVariable    = new Variable("object");
 
-                List<Object> selectList = new ArrayList<Object>(3);
+                List<SelectElement> selectList = new ArrayList<SelectElement>(3);
                 selectList.add(subjectVariable);
                 selectList.add(predicateVariable);
                 selectList.add(objectVariable);
@@ -1392,7 +1483,7 @@
         Variable varB   = new Variable("b");
         Variable varT = new Variable("t");
 
-        List<Object> selectList = new ArrayList<Object>(2);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(2);
         selectList.add(varA);
         selectList.add(varT);
 

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ApplyRulesOperation.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/ApplyRulesOperation.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ApplyRulesOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ApplyRulesOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,89 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.resolver;
+
+// Java 2 standard packages
+import java.rmi.RemoteException;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.QueryException;
+import org.mulgara.resolver.spi.DatabaseMetadata;
+import org.mulgara.resolver.spi.SystemResolver;
+import org.mulgara.rules.Rules;
+import org.mulgara.rules.RulesRef;
+
+/**
+ * An {@link Operation} that applies a set of rules to a graph. These rules are built with
+ * the corresponding {@link BuildRulesOperation}.
+ *
+ * @created Mar 25, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+class ApplyRulesOperation implements Operation {
+
+  @SuppressWarnings("unused")
+  /** Logger. */
+  private static final Logger logger = Logger.getLogger(ApplyRulesOperation.class.getName());
+
+  /** The rules to run in this operation. */
+  Rules rules;
+
+  /**
+   * Create and set up the operation.
+   *
+   * @param rulesRef A reference to the rules that this operation will execute.
+   * @throws IllegalArgumentException if the rules are null.
+   * @throws QueryException if the rules reference could not be accessed over a network.
+   */
+  public ApplyRulesOperation(RulesRef rulesRef) throws QueryException {
+    if (rulesRef == null) throw new IllegalArgumentException("Illegal to use a null set of rules");
+    try {
+      rules = rulesRef.getRules();
+    } catch (RemoteException e) {
+      throw new QueryException("Unable to read rules from server", e);
+    }
+  }
+
+  /**
+   * @see org.mulgara.resolver.Operation#execute(org.mulgara.resolver.OperationContext, org.mulgara.resolver.spi.SystemResolver, org.mulgara.resolver.spi.ResolverSessionFactory, org.mulgara.resolver.spi.DatabaseMetadata)
+   * Runs the rules over the configured data.
+   */
+  public void execute(OperationContext         operationContext,
+                      SystemResolver           systemResolver,
+                      DatabaseMetadata         metadata) throws Exception {
+    rules.run(packageParams(operationContext, systemResolver));
+  }
+
+  /**
+   * @see org.mulgara.resolver.Operation#isWriteOperation()
+   * @return <code>true</code>
+   */
+  public boolean isWriteOperation() {
+    return true;
+  }
+  
+  /**
+   * Packages up the parameters for the rules to run with.
+   * This was a Session, and will become a Session, but for the moment it is the
+   * OperationContext and SystemResolver.
+   * TODO: change this back to Session
+   */
+  private Object[] packageParams(OperationContext context, SystemResolver resolver) {
+    return new Object[] { context, resolver };
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BackupOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BackupOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BackupOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -101,7 +101,6 @@
 
   public void execute(OperationContext operationContext,
       SystemResolver systemResolver,
-      ResolverSessionFactory resolverSessionFactory,
       DatabaseMetadata metadata) throws Exception {
     OutputStream os = outputStream;
     Writer writer = null;
@@ -140,9 +139,7 @@
             new GZIPOutputStream(os), "UTF-8"
         ));
 
-        StringPool stringPool =
-            resolverSessionFactory.getPersistentStringPool();
-        backupDatabase(stringPool, systemResolver, metadata, writer);
+        backupDatabase(systemResolver, metadata, writer);
       }
     } finally {
       // Clean up.
@@ -167,10 +164,8 @@
    * @param writer Writer
    * @throws Exception
    */
-  private void backupDatabase(
-      StringPool stringPool, Resolver resolver,
-      DatabaseMetadata metadata, Writer writer
-  ) throws Exception {
+  private void backupDatabase(SystemResolver systemResolver, DatabaseMetadata metadata, Writer writer)
+      throws Exception {
     // Write the backup
     writer.write(BACKUP_FILE_HEADER + BACKUP_VERSION + '\n');
     writer.write(new Date().toString());
@@ -179,7 +174,7 @@
     // Dump the strings.
     writer.write("RDFNODES\n");
 
-    Tuples t = stringPool.findGNodes(null, null);
+    Tuples t = systemResolver.findStringPoolType(null, null);
     assert t != null;
     try {
       t.beforeFirst();
@@ -188,7 +183,7 @@
         writer.write(Long.toString(localNode));
         writer.write(' ');
 
-        SPObject spObject = stringPool.findSPObject(localNode);
+        SPObject spObject = systemResolver.findSPObject(localNode);
         writer.write(spObject.getEncodedString());
         writer.write('\n');
       }
@@ -197,7 +192,7 @@
     }
 
     // Dump the triples.
-    Tuples tuples = resolver.resolve(new ConstraintImpl(
+    Tuples tuples = systemResolver.resolve(new ConstraintImpl(
         StatementStore.VARIABLES[0],
         StatementStore.VARIABLES[1],
         StatementStore.VARIABLES[2],

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BasicDatabaseSessionUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BasicDatabaseSessionUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BasicDatabaseSessionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -187,7 +187,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);
@@ -276,7 +276,7 @@
         Variable predicateVariable = new Variable("predicate");
         Variable objectVariable    = new Variable("object");
 
-        List<Object> selectList = new ArrayList<Object>(3);
+        List<SelectElement> selectList = new ArrayList<SelectElement>(3);
         selectList.add(subjectVariable);
         selectList.add(predicateVariable);
         selectList.add(objectVariable);

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BootstrapOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BootstrapOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BootstrapOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -38,7 +38,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception {
     // Find the local node identifying the model
     long model = systemResolver.localizePersistent(

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BuildRulesOperation.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/BuildRulesOperation.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BuildRulesOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/BuildRulesOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,103 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.resolver;
+
+// Java 2 standard packages
+import java.net.URI;
+
+// Local packages
+import org.mulgara.resolver.spi.*;
+import org.mulgara.rules.RuleLoader;
+import org.mulgara.rules.RuleLoaderFactory;
+import org.mulgara.rules.Rules;
+import org.mulgara.rules.RulesRef;
+import org.mulgara.rules.RulesRefImpl;
+
+//Third party packages
+import org.apache.log4j.Logger;
+
+/**
+ * Represents an operation to build a Rule structure for later execution
+ *
+ * @created Mar 25, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+class BuildRulesOperation implements Operation {
+
+  @SuppressWarnings("unused")
+  /** Logger. */
+  private static final Logger logger = Logger.getLogger(BuildRulesOperation.class.getName());
+
+  /** The graph containing the rules to run */
+  private URI ruleGraph = null;
+
+  /** The graph containing the intrinsic data */
+  private URI baseGraph = null;
+
+  /** The graph to contain the generated extrinsic data */
+  private URI destGraph = null;
+
+  /** The name of the class that loads rules */
+  private String ruleLoaderClassName = null;
+
+  /** The rules structure that can be shipped over RMI */
+  private RulesRefImpl result;
+
+
+  /**
+   * Create an configure this operation.
+   * @param ruleLoaderClassName The name of the class that can load the configured rules.
+   * @param ruleGraph The graph containing the rules to read.
+   * @param baseGraph The graph the rules will be run on.
+   * @param destGraph The graph the rules will insert generated statements into.
+   */
+  BuildRulesOperation(String ruleLoaderClassName, URI ruleGraph, URI baseGraph, URI destGraph) {
+    this.ruleLoaderClassName = ruleLoaderClassName;
+    this.ruleGraph = ruleGraph;
+    this.baseGraph = baseGraph;
+    this.destGraph = destGraph;
+  }
+
+  /**
+   * @see org.mulgara.resolver.Operation#execute(org.mulgara.resolver.OperationContext, org.mulgara.resolver.spi.SystemResolver, org.mulgara.resolver.spi.ResolverSessionFactory, org.mulgara.resolver.spi.DatabaseMetadata)
+   */
+  public void execute(OperationContext       operationContext,
+                      SystemResolver         systemResolver,
+                      DatabaseMetadata       metadata) throws Exception {
+    // Set up the rule parser
+    RuleLoader ruleLoader = RuleLoaderFactory.newRuleLoader(ruleLoaderClassName, ruleGraph, baseGraph, destGraph);
+    if (ruleLoader == null) throw new org.mulgara.rules.InitializerException("No rule loader available");
+  
+    // read in the rules
+    Rules rules =  ruleLoader.readRules(operationContext, metadata.getSystemModelURI());
+    result = new RulesRefImpl(rules);
+  }
+
+  /**
+   * @see org.mulgara.resolver.Operation#isWriteOperation()
+   */
+  public boolean isWriteOperation() {
+    return false;
+  }
+
+  /**
+   * Obtains the results of this operation, after the transactional work is completed.
+   * @return A reference to a set of rules.
+   */  
+  RulesRef getResult() {
+    return result;
+  }
+
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/CreateModelOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/CreateModelOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/CreateModelOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,105 +28,62 @@
 package org.mulgara.resolver;
 
 // Java 2 standard packages
-import java.io.*;
-import java.net.MalformedURLException;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.*;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
 
-// Java 2 enterprise packages
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.InvalidTransactionException;
-
 // Third party packages
 import org.apache.log4j.Logger;
 import org.jrdf.graph.*;
 
 // Local packages
-import org.mulgara.content.Content;
-import org.mulgara.content.ContentHandler;
-import org.mulgara.content.ContentHandlerManager;
-import org.mulgara.content.ContentLoader;
 import org.mulgara.query.*;
 import org.mulgara.query.rdf.*;
 import org.mulgara.resolver.spi.*;
-import org.mulgara.resolver.url.URLResolver;
 import org.mulgara.server.Session;
 import org.mulgara.store.nodepool.NodePool;
 
 /**
  * An {@link Operation} that implements the {@link Session#createModel} method.
+ * TODO: Rename to CreateGraphOperation.
  *
  * @created 2004-11-24
- *
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
  * @version $Revision: 1.9 $
- *
  * @modified $Date: 2005/02/22 08:16:08 $ by $Author: newmana $
- *
  * @maintenanceAuthor $Author: newmana $
- *
- * @copyright &copy;2004 <a href="http://www.tucanatech.com/">Tucana
- *   Technology, Inc</a>
- *
+ * @copyright &copy;2004 <a href="http://www.tucanatech.com/">Tucana  Technology, Inc</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-class CreateModelOperation implements Operation
-{
-  /**
-   * Logger.
-   *
-   * This is named after the class.
-   */
-  private static final Logger logger =
-    Logger.getLogger(CreateModelOperation.class.getName());
+class CreateModelOperation implements Operation {
+  /** Logger. This is named after the class. */
+  @SuppressWarnings("unused")
+  private static final Logger logger = Logger.getLogger(CreateModelOperation.class.getName());
 
-  /**
-   * The URI of the model to be created.
-   */
-  private final URI modelURI;
+  /** The URI of the model to be created. */
+  private final URI graphURI;
 
-  /**
-   * The URI of the type of the model to be created.
-   */
-  private URI modelTypeURI;
+  /** The URI of the type of the model to be created. */
+  private URI graphTypeURI;
 
-  //
-  // Constructor
-  //
 
   /**
    * Sole constructor.
    *
-   * @param modelURI  the {@link URI} of the model to be created, never
-   *   <code>null</code>
-   * @param modelTypeURI  thie {@link URI} of the type of model to create, or
-   *   <code>null</code> for the same type as the system model (<code>#</code>)
-   * @throws IllegalArgumentException if <var>modelURI</var> is
-   *   <code>null</code>
+   * @param graphURI  the {@link URI} of the graph to be created, never <code>null</code>
+   * @param graphTypeURI  thie {@link URI} of the type of graph to create, or
+   *       <code>null</code> for the same type as the system graph (<code>#</code>)
+   * @throws IllegalArgumentException if <var>graphURI</var> is <code>null</code>
    */
-  CreateModelOperation(URI modelURI, URI modelTypeURI) throws QueryException
-  {
-    // Validate "modelURI" parameter
-    if (modelURI == null) {
-      throw new IllegalArgumentException("Null \"modelURI\" parameter");
+  CreateModelOperation(URI graphURI, URI graphTypeURI) throws QueryException {
+    // Validate "graphURI" parameter
+    if (graphURI == null) throw new IllegalArgumentException("Null \"graphURI\" parameter");
+    if (!graphURI.isOpaque() && graphURI.getFragment() == null) {
+      throw new QueryException("Graph URI does not have a fragment (graphURI:\"" + graphURI + "\")");
     }
-    if (modelURI.getFragment() == null) {
-      throw new QueryException(
-          "Model URI does not have a fragment (modelURI:\"" + modelURI + "\")"
-      );
-    }
 
     // Initialize fields
-    this.modelURI     = modelURI;
-    this.modelTypeURI = modelTypeURI;
+    this.graphURI     = graphURI;
+    this.graphTypeURI = graphTypeURI;
   }
 
   //
@@ -135,76 +92,16 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
-                      DatabaseMetadata       metadata) throws Exception
-  {
-    // Default to the system model type
-    if (modelTypeURI == null) {
-      modelTypeURI = metadata.getSystemModelTypeURI();
-    }
+                      DatabaseMetadata       metadata) throws Exception {
+    // Default to the system graph type
+    if (graphTypeURI == null) graphTypeURI = metadata.getSystemModelTypeURI();
 
-    // Verify that the model URI is relative to the database URI.  The model
-    // URI can use one of the hostname aliases instead of the canonical
-    // hostname of the database URI.  No checking of the scheme specific part
-    // of the model URI is performed if the database URI is opaque.
-    boolean badModelURI = true;
-    URI databaseURI = metadata.getURI();
-    String scheme = modelURI.getScheme();
-    String fragment = modelURI.getFragment();
-    if (scheme != null && scheme.equals(databaseURI.getScheme()) &&
-        fragment != null) {
-      if (databaseURI.isOpaque()) {
-        // databaseURI is opaque.
-        if (modelURI.isOpaque()) {
-          // Strip out the query string.
-          String ssp = modelURI.getSchemeSpecificPart();
-          int qIndex = ssp.indexOf('?');
-          if (qIndex >= 0) {
-            ssp = ssp.substring(0, qIndex);
-          }
-
-          if (ssp.equals(databaseURI.getSchemeSpecificPart())) {
-            // modelURI is relative to databaseURI.
-            badModelURI = false;
-          }
-        }
-      } else {
-        // databaseURI is hierarchial.
-        String path;
-        String host;
-
-        if (
-            !modelURI.isOpaque() && (
-                modelURI.getSchemeSpecificPart().equals(
-                    databaseURI.getSchemeSpecificPart()
-                ) || (
-                    (host = modelURI.getHost()) != null &&
-                    modelURI.getPort() == databaseURI.getPort() &&
-                    (path = modelURI.getPath()) != null &&
-                    path.equals(databaseURI.getPath()) &&
-                    metadata.getHostnameAliases().contains(host.toLowerCase())
-                )
-            )
-        ) {
-          // modelURI is relative to databaseURI.
-          badModelURI = false;
-        }
-      }
-    }
-    if (badModelURI) {
-      throw new QueryException(
-          "Model URI is not relative to the database URI (modelURI:\"" +
-          modelURI + "\", databaseURI:\"" + databaseURI + "\")"
-      );
-    }
-
+    verifyGraphUriIsRelative(graphURI, metadata);
+    
     // Look up the resolver factory for the model type
-    ResolverFactory resolverFactory =
-      operationContext.findModelTypeResolverFactory(modelTypeURI);
+    ResolverFactory resolverFactory = operationContext.findModelTypeResolverFactory(graphTypeURI);
     if (resolverFactory == null) {
-      throw new QueryException(
-          "Couldn't find resolver factory in internal resolver map " +
-          modelTypeURI);
+      throw new QueryException("Couldn't find resolver factory in internal resolver map " + graphTypeURI);
     }
 
     // PREVIOUSLY WITHIN TRANSACTION
@@ -214,14 +111,13 @@
     assert resolver != null;
 
     // Find the local node identifying the model
-    long model = systemResolver.localizePersistent(new URIReferenceImpl(
-        modelURI));
-    assert model != NodePool.NONE;
+    long graph = systemResolver.localizePersistent(new URIReferenceImpl(graphURI));
+    assert graph != NodePool.NONE;
 
     // Check model does not already exist with a different model type.
     // TODO: there's a node leak here, if the model has already been created.
     Resolution resolution = systemResolver.resolve(new ConstraintImpl(
-        new LocalNode(model),
+        new LocalNode(graph),
         new LocalNode(metadata.getRdfTypeNode()),
         new Variable("x"),
         new LocalNode(metadata.getSystemModelNode())));
@@ -232,12 +128,12 @@
         Node eNode = systemResolver.globalize(resolution.getColumnValue(0));
         try {
           URIReferenceImpl existing = (URIReferenceImpl)eNode;
-          if (!new URIReferenceImpl(modelTypeURI).equals(existing)) {
-            throw new QueryException(modelURI + " already exists with model type " + existing +
-                " in attempt to create it with type " + modelTypeURI);
+          if (!new URIReferenceImpl(graphTypeURI).equals(existing)) {
+            throw new QueryException(graphURI + " already exists with model type " + existing +
+                " in attempt to create it with type " + graphTypeURI);
           }
         } catch (ClassCastException ec) {
-          throw new QueryException("Invalid model type entry in system model: " + modelURI + " <rdf:type> " + eNode);
+          throw new QueryException("Invalid model type entry in system model: " + graphURI + " <rdf:type> " + eNode);
         }
       }
     } finally {
@@ -250,28 +146,86 @@
     //       following security check doesn't succeed
 
     // Make sure security adapters are satisfied
-    for (Iterator i = operationContext.getSecurityAdapterList().iterator();
-         i.hasNext();)
-    {
-      SecurityAdapter securityAdapter = (SecurityAdapter) i.next();
+    for (Iterator<SecurityAdapter> i = operationContext.getSecurityAdapterList().iterator(); i.hasNext();) {
+      SecurityAdapter securityAdapter = i.next();
 
       // Tell the truth to the user
-      if (!securityAdapter.canCreateModel(model, systemResolver) ||
-          !securityAdapter.canSeeModel(model, systemResolver))
-      {
-        throw new QueryException("You aren't allowed to create " + modelURI);
+      if (!securityAdapter.canCreateModel(graph, systemResolver) || !securityAdapter.canSeeModel(graph, systemResolver)) {
+        throw new QueryException("You aren't allowed to create " + graphURI);
       }
     }
 
     // Use the session to create the model
-    resolver.createModel(model, modelTypeURI);
+    resolver.createModel(graph, graphTypeURI);
   }
 
   /**
    * @return <code>true</code>
    */
-  public boolean isWriteOperation()
-  {
+  public boolean isWriteOperation() {
     return true;
   }
+
+  /**
+   * Verify that the graph URI is relative to the database URI.  The graph
+   * URI can use one of the hostname aliases instead of the canonical
+   * hostname of the database URI.  No checking of the scheme specific part
+   * of the graph URI is performed if the database URI is opaque.
+   * @param graphURI
+   * @param metadata
+   * @throws QueryException
+   */
+  private void verifyGraphUriIsRelative(URI graphURI, DatabaseMetadata metadata) throws QueryException {
+    boolean badModelURI = true;
+    URI databaseURI = metadata.getURI();
+    String scheme = graphURI.getScheme();
+    String fragment = graphURI.getFragment();
+
+    if (scheme != null && scheme.equals(databaseURI.getScheme()) && fragment != null) {
+      if (databaseURI.isOpaque()) {
+        // databaseURI is opaque.
+        if (graphURI.isOpaque()) {
+          // Strip out the query string.
+          String ssp = graphURI.getSchemeSpecificPart();
+          int qIndex = ssp.indexOf('?');
+          if (qIndex >= 0) ssp = ssp.substring(0, qIndex);
+
+          if (ssp.equals(databaseURI.getSchemeSpecificPart())) {
+            // graphURI is relative to databaseURI.
+            badModelURI = false;
+          }
+        }
+      } else {
+        // databaseURI is hierarchial.
+        String path;
+        String host;
+
+        if (
+            !graphURI.isOpaque() && (
+                graphURI.getSchemeSpecificPart().equals(
+                    databaseURI.getSchemeSpecificPart()
+                ) || (
+                    (host = graphURI.getHost()) != null &&
+                    graphURI.getPort() == databaseURI.getPort() &&
+                    (path = graphURI.getPath()) != null &&
+                    path.equals(databaseURI.getPath()) &&
+                    metadata.getHostnameAliases().contains(host.toLowerCase())
+                )
+            )
+        ) {
+          // graphURI is relative to databaseURI.
+          badModelURI = false;
+        }
+      }
+    } else {
+      badModelURI = !graphURI.isOpaque();
+    }
+
+    if (badModelURI) {
+      throw new QueryException(
+          "Model URI is not relative to the database URI (graphURI:\"" +
+          graphURI + "\", databaseURI:\"" + databaseURI + "\")"
+      );
+    }
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,9 +16,11 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * 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
@@ -34,6 +36,9 @@
 import java.net.URI;
 import java.util.*;
 
+// Java 2 enterprise packages
+import javax.transaction.xa.XAResource;
+
 // Third party packages
 import org.apache.log4j.Logger;
 import org.jrdf.graph.*;
@@ -113,6 +118,10 @@
   /** Source of transactions.  */
   private final MulgaraTransactionManager transactionManager;
 
+  private MulgaraTransactionFactory transactionFactory;
+  private MulgaraInternalTransactionFactory internalFactory;
+  private MulgaraExternalTransactionFactory externalFactory;
+
   /** The name of the rule loader to use */
   private String ruleLoaderClassName;
 
@@ -226,6 +235,9 @@
     this.temporaryModelTypeURI      = temporaryModelTypeURI;
     this.ruleLoaderClassName        = ruleLoaderClassName;
 
+    this.transactionFactory = null;
+    this.internalFactory = null;
+
     if (logger.isDebugEnabled()) {
       logger.debug("Constructed DatabaseSession");
     }
@@ -297,7 +309,7 @@
   // Methods implementing Session
   //
 
-  public void insert(URI modelURI, Set<Triple> statements) throws QueryException {
+  public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException {
     modify(modelURI, statements, ASSERT_STATEMENTS);
   }
 
@@ -305,7 +317,7 @@
     modify(modelURI, query, ASSERT_STATEMENTS);
   }
 
-  public void delete(URI modelURI, Set<Triple> statements) throws QueryException {
+  public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException {
     modify(modelURI, statements, DENY_STATEMENTS);
   }
 
@@ -481,28 +493,19 @@
   /**
    * {@inheritDoc}
    */
-  public RulesRef buildRules(URI ruleModel, URI baseModel, URI destModel) throws QueryException, org.mulgara.rules.InitializerException, java.rmi.RemoteException {
-    if (logger.isInfoEnabled()) {
-      logger.info("BUILD RULES: " + ruleModel);
-    }
+  public RulesRef buildRules(URI ruleModel, URI baseModel, URI destModel) throws QueryException, org.mulgara.rules.InitializerException {
+    if (logger.isInfoEnabled()) logger.info("BUILD RULES: " + ruleModel);
 
-    // Set up the rule parser
-    RuleLoader ruleLoader = RuleLoaderFactory.newRuleLoader(ruleLoaderClassName, ruleModel, baseModel, destModel);
-    if (ruleLoader == null) {
-      throw new org.mulgara.rules.InitializerException("No rule loader available");
-    }
-
-    // read in the rules
-    Rules rules =  ruleLoader.readRules(this, metadata.getSystemModelURI());
-    return new RulesRefImpl(rules);
+    BuildRulesOperation operation = new BuildRulesOperation(ruleLoaderClassName, ruleModel, baseModel, destModel);
+    execute(operation, "Failed to create rules");
+    return operation.getResult();
   }
 
   /**
    * {@inheritDoc}
    */
-  public void applyRules(RulesRef rulesRef) throws RulesException, java.rmi.RemoteException {
-    Rules rules = rulesRef.getRules();
-    rules.run(this);
+  public void applyRules(RulesRef rulesRef) throws QueryException {
+    execute(new ApplyRulesOperation(rulesRef), "Unable to apply rules");
   }
 
 
@@ -510,8 +513,9 @@
     if (logger.isInfoEnabled()) {
       logger.info("setAutoCommit(" + autoCommit + ") called.");
     }
+    assertInternallyManagedXA();
     try {
-      transactionManager.setAutoCommit(this, autoCommit);
+      internalFactory.setAutoCommit(this, autoCommit);
     } catch (MulgaraTransactionException em) {
       throw new QueryException("Error setting autocommit", em);
     }
@@ -519,8 +523,9 @@
 
   public void commit() throws QueryException {
     logger.info("Committing transaction");
+    assertInternallyManagedXA();
     try {
-      transactionManager.commit(this);
+      internalFactory.commit(this);
     } catch (MulgaraTransactionException em) {
       throw new QueryException("Error performing commit", em);
     }
@@ -528,8 +533,9 @@
 
   public void rollback() throws QueryException {
     logger.info("Rollback transaction");
+    assertInternallyManagedXA();
     try {
-      transactionManager.rollback(this);
+      internalFactory.rollback(this);
     } catch (MulgaraTransactionException em) {
       throw new QueryException("Error performing rollback", em);
     }
@@ -538,9 +544,11 @@
   public void close() throws QueryException {
     logger.info("Closing session");
     try {
-      transactionManager.rollbackCurrentTransactions(this);
-    } catch (MulgaraTransactionException em) {
-      throw new QueryException("Error closing session. Forced close required", em);
+      transactionManager.closingSession(this);
+      transactionFactory = null;
+    } catch (MulgaraTransactionException em2) {
+      logger.error("Error force-closing session", em2);
+      throw new QueryException("Error force-closing session.", em2);
     }
   }
 
@@ -574,25 +582,23 @@
    */
   private synchronized void backup(OutputStream outputStream, URI serverURI, URI destinationURI)
       throws QueryException {
-    execute(
-        new BackupOperation(outputStream, serverURI, destinationURI),
+    execute(new BackupOperation(outputStream, serverURI, destinationURI),
         "Unable to backup to " + destinationURI);
   }
 
   //
   // Internal utility methods.
   //
-  protected void modify(URI modelURI, Set<Triple> statements, boolean insert) throws QueryException
+  protected void modify(URI modelURI, Set<? extends Triple> statements, boolean insert) throws QueryException
   {
     if (logger.isInfoEnabled()) {
-      logger.info("Inserting statements into " + modelURI);
+      logger.info("Modifying (ins:" + insert + ") : " + modelURI);
     }
     if (logger.isDebugEnabled()) {
-      logger.debug("Inserting statements: " + statements);
+      logger.debug("Modifying statements: " + statements);
     }
 
-    execute(new ModifyModelOperation(modelURI, statements, insert),
-            "Could not commit insert");
+    execute(new ModifyModelOperation(modelURI, statements, insert), "Could not commit modify");
   }
 
   private void modify(URI modelURI, Query query, boolean insert) throws QueryException
@@ -602,7 +608,7 @@
     }
 
     execute(new ModifyModelOperation(modelURI, query, insert, this),
-            "Unable to modify " + modelURI);
+        "Unable to modify " + modelURI);
   }
 
   /**
@@ -611,12 +617,12 @@
    * @param operation  the {@link Operation} to execute
    * @throws QueryException if the <var>operation</var> fails
    */
-  private void execute(Operation operation, String errorString) throws QueryException
-  {
+  private void execute(Operation operation, String errorString) throws QueryException {
+    ensureTransactionFactorySelected();
     try {
       MulgaraTransaction transaction =
-          transactionManager.getTransaction(this, operation.isWriteOperation());
-      transaction.execute(operation, resolverSessionFactory, metadata);
+          transactionFactory.getTransaction(this, operation.isWriteOperation());
+      transaction.execute(operation, metadata);
     } catch (MulgaraTransactionException em) {
       logger.info("Error executing operation: " + errorString, em);
       throw new QueryException(errorString, em);
@@ -636,4 +642,36 @@
         systemResolverFactory,
         writing);
   }
+
+  private void ensureTransactionFactorySelected() throws QueryException {
+    if (transactionFactory == null) {
+      assertInternallyManagedXA();
+    }
+  }
+
+  private void assertInternallyManagedXA() throws QueryException {
+    if (transactionFactory == null) {
+      transactionFactory = internalFactory = transactionManager.getInternalFactory();
+    } else if (internalFactory == null) {
+      throw new QueryException("Attempt to use internal transaction control in externally managed session");
+    }
+  }
+
+  private void assertExternallyManagedXA() throws QueryException {
+    if (transactionFactory == null) {
+      transactionFactory = externalFactory = transactionManager.getExternalFactory();
+    } else if (externalFactory == null) {
+      throw new QueryException("Attempt to use external transaction control in internally managed session");
+    }
+  }
+
+  public XAResource getXAResource() throws QueryException {
+    assertExternallyManagedXA();
+    return externalFactory.getXAResource(this, true);
+  }
+
+  public XAResource getReadOnlyXAResource() throws QueryException {
+    assertExternallyManagedXA();
+    return externalFactory.getXAResource(this, false);
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionListQueryUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionListQueryUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionListQueryUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -282,7 +282,7 @@
   private Query selectAll(URI modelURI) throws Exception {
 
     //select $s $p $o
-    ConstraintElement [] vars = new Variable[] {
+    Variable[] vars = new Variable[] {
         StatementStore.VARIABLES[0],
         StatementStore.VARIABLES[1],
         StatementStore.VARIABLES[2]
@@ -295,7 +295,7 @@
     ConstraintImpl varConstraint = new ConstraintImpl(vars[0], vars[1], vars[2]);
 
     return new Query(
-        Arrays.asList((Object[])vars), // variable list
+        Arrays.asList((SelectElement[])vars), // variable list
         model, // model expression
         varConstraint, // constraint expr
         null, // no having

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DatabaseSessionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -558,7 +558,7 @@
 
         // Evaluate the query
         Answer answer = new ArrayAnswer(session.query(new Query(
-          (List<Object>)(List)test.selectList,  // SELECT
+          test.selectList,          // SELECT
           test.model,               // FROM
           test.query,               // WHERE
           null,                     // HAVING

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -201,6 +201,7 @@
             }
           }
         }),
+/*
         new NVPair(ConstraintNegation.class, new ConstraintResolutionHandler() {
           public Tuples resolve(QueryEvaluationContext context, ModelExpression modelExpr, ConstraintExpression constraintExpr) throws Exception {
             if (((ConstraintNegation)constraintExpr).getModel().equals(Variable.FROM)) {
@@ -215,6 +216,7 @@
             }
           }
         }),
+*/
         new NVPair(WalkConstraint.class, new ConstraintResolutionHandler() {
           public Tuples resolve(QueryEvaluationContext context, ModelExpression modelExpr, ConstraintExpression constraintExpr) throws Exception {
             return WalkFunction.walk(context, (WalkConstraint)constraintExpr, modelExpr, context.getResolverSession());
@@ -291,11 +293,13 @@
                                       ConstraintOperations.replace(bindings, wc.getUnanchoredConstraint()));
           }
         }),
+/*
         new NVPair(ConstraintNegation.class, new ConstraintBindingHandler() {
           public ConstraintExpression bindVariables(Map bindings, ConstraintExpression constraintExpr) throws Exception {
             return new ConstraintNegation(ConstraintOperations.replace(bindings, (Constraint)constraintExpr));
           }
         }),
+*/
         new NVPair(ConstraintFilter.class, new ConstraintBindingHandler() {
           public ConstraintExpression bindVariables(Map bindings, ConstraintExpression constraintExpr) throws Exception {
             return new ConstraintFilter(ConstraintOperations.replace(bindings, (Constraint)constraintExpr), ((ConstraintFilter)constraintExpr).getFilter());
@@ -329,11 +333,13 @@
             return new ConstraintImpl(constraint.getElement(0), constraint.getElement(1), constraint.getElement(2), newModel);
           }
         }),
+/*
         new NVPair(ConstraintNegation.class, new ConstraintModelRewrite() {
           public Constraint rewrite(ConstraintElement newModel, Constraint constraint) throws Exception {
             return new ConstraintNegation(new ConstraintImpl(constraint.getElement(0), constraint.getElement(1), constraint.getElement(2), newModel));
           }
         }),
+*/
       });
   }
 
@@ -349,6 +355,7 @@
                 context.localize(constraint.getElement(3)));
           }
         }),
+/*
         new NVPair(ConstraintNegation.class, new ConstraintLocalization() {
           public Constraint localize(QueryEvaluationContext context, Constraint constraint) throws Exception {
             return new ConstraintNegation(new ConstraintImpl(
@@ -358,6 +365,7 @@
                 context.localize(constraint.getElement(3))));
           }
         }),
+*/
       });
   }
 }

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ExternalTransactionUnitTest.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/ExternalTransactionUnitTest.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ExternalTransactionUnitTest.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ExternalTransactionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2025 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com) under contract to 
+ * Topaz Foundation. Portions created under this contract are
+ * Copyright (c) 2007 Topaz Foundation
+ * All Rights Reserved.
+ *
+ * scaffolding based on AdvDatabaseSessionUnitTest.java
+ */
+
+package org.mulgara.resolver;
+
+// Java 2 standard packages
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import junit.framework.*;        // JUnit
+import org.apache.log4j.Logger;  // Log4J
+import org.jrdf.graph.SubjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.ObjectNode;
+
+// Locally written packages
+import org.mulgara.query.*;
+import org.mulgara.query.rdf.Mulgara;
+import org.mulgara.query.rdf.URIReferenceImpl;
+import org.mulgara.query.rdf.TripleImpl;
+import org.mulgara.server.Session;
+import org.mulgara.util.FileUtil;
+
+/**
+ * Testing Externally Mediated Transactions. 
+ *
+ * @created 2007-11-27
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ * @company <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
+ *      Software Pty Ltd</a>
+ * @copyright &copy;2006 <a href="http://www.topazproject.org/">Topaz Project
+ * Foundation</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public class ExternalTransactionUnitTest extends TestCase
+{
+  /** Logger.  */
+  private static Logger logger =
+    Logger.getLogger(ExternalTransactionUnitTest.class.getName());
+
+  private static final URI databaseURI;
+
+  private static final URI systemModelURI;
+
+  private static final URI modelURI;
+  private static final URI model2URI;
+  private static final URI model3URI;
+  private static final URI model4URI;
+  private static final URI model5URI;
+
+  static {
+    try {
+      databaseURI    = new URI("local://database");
+      systemModelURI = new URI("local://database#");
+      modelURI       = new URI("local://database#model");
+      model2URI      = new URI("local://database#model2");
+      model3URI      = new URI("local://database#model3");
+      model4URI      = new URI("local://database#model4");
+      model5URI      = new URI("local://database#model5");
+    } catch (URISyntaxException e) {
+      throw new Error("Bad hardcoded URI", e);
+    }
+  }
+
+  private static Database database = null;
+
+  public ExternalTransactionUnitTest(String name)
+  {
+    super(name);
+  }
+
+  public static Test suite()
+  {
+    TestSuite suite = new TestSuite();
+    suite.addTest(new ExternalTransactionUnitTest("testSimpleOnePhaseCommit"));
+    suite.addTest(new ExternalTransactionUnitTest("testSimpleTwoPhaseCommit"));
+    suite.addTest(new ExternalTransactionUnitTest("testBasicQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testMultipleQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testBasicReadOnlyQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testConcurrentQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testConcurrentReadWrite"));
+    suite.addTest(new ExternalTransactionUnitTest("testSubqueryQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testConcurrentSubqueryQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testExplicitIsolationQuerySingleSession"));
+    suite.addTest(new ExternalTransactionUnitTest("testConcurrentExplicitTxn"));
+    suite.addTest(new ExternalTransactionUnitTest("testExplicitRollbackIsolationQuery"));
+    suite.addTest(new ExternalTransactionUnitTest("testExternalInternalIsolation"));
+    suite.addTest(new ExternalTransactionUnitTest("testInternalExternalIsolation"));
+    suite.addTest(new ExternalTransactionUnitTest("testInternalExternalConcurrentTxn"));
+    suite.addTest(new ExternalTransactionUnitTest("testExternalInternalConcurrentTxn"));
+    suite.addTest(new ExternalTransactionUnitTest("testInternalExternalConcurrentTxnRollback"));
+    suite.addTest(new ExternalTransactionUnitTest("testExternalInternalConcurrentTxnRollback"));
+    suite.addTest(new ExternalTransactionUnitTest("testInternalSerialMultipleSessions"));
+
+    return suite;
+  }
+
+  /**
+   * Create test objects.
+   */
+  public void setUp() throws Exception {
+    if (database == null) {
+      // Create the persistence directory
+      File persistenceDirectory =
+        new File(new File(System.getProperty("cvs.root")), "testDatabase");
+      if (persistenceDirectory.isDirectory()) {
+        if (!FileUtil.deleteDirectory(persistenceDirectory)) {
+          throw new RuntimeException(
+            "Unable to remove old directory " + persistenceDirectory
+          );
+        }
+      }
+      if (!persistenceDirectory.mkdirs()) {
+        throw new Exception("Unable to create directory "+persistenceDirectory);
+      }
+
+      // Define the the node pool factory
+      String nodePoolFactoryClassName =
+        "org.mulgara.store.nodepool.xa.XANodePoolFactory";
+
+      // Define the string pool factory
+      String stringPoolFactoryClassName =
+        "org.mulgara.store.stringpool.xa.XAStringPoolFactory";
+
+      String tempNodePoolFactoryClassName =
+        "org.mulgara.store.nodepool.memory.MemoryNodePoolFactory";
+
+      // Define the string pool factory
+      String tempStringPoolFactoryClassName =
+        "org.mulgara.store.stringpool.memory.MemoryStringPoolFactory";
+
+      // Define the resolver factory used to manage system models
+      String systemResolverFactoryClassName =
+        "org.mulgara.resolver.store.StatementStoreResolverFactory";
+
+      // Define the resolver factory used to manage system models
+      String tempResolverFactoryClassName =
+        "org.mulgara.resolver.memory.MemoryResolverFactory";
+
+      String ruleLoaderFactoryClassName =
+        "org.mulgara.rules.RuleLoaderFactory";
+
+      // Create a database which keeps its system models on the Java heap
+      database = new Database(
+                   databaseURI,
+                   persistenceDirectory,
+                   null,                            // no security domain
+                   new JotmTransactionManagerFactory(),
+                   0,                               // default transaction timeout
+                   nodePoolFactoryClassName,        // persistent
+                   new File(persistenceDirectory, "xaNodePool"),
+                   stringPoolFactoryClassName,      // persistent
+                   new File(persistenceDirectory, "xaStringPool"),
+                   systemResolverFactoryClassName,  // persistent
+                   new File(persistenceDirectory, "xaStatementStore"),
+                   tempNodePoolFactoryClassName,    // temporary nodes
+                   null,                            // no dir for temp nodes
+                   tempStringPoolFactoryClassName,  // temporary strings
+                   null,                            // no dir for temp strings
+                   tempResolverFactoryClassName,    // temporary models
+                   null,                            // no dir for temp models
+                   "",                              // no rule loader
+                   "org.mulgara.content.rdfxml.RDFXMLContentHandler");
+
+      database.addResolverFactory("org.mulgara.resolver.url.URLResolverFactory", null);
+    }
+  }
+
+
+  /**
+  * The teardown method for JUnit
+  */
+  public void tearDown()
+  {
+  }
+
+  //
+  // Test cases
+  //
+
+  private static class TestXid implements Xid {
+    private int xid;
+    public TestXid(int xid) {
+      this.xid = xid;
+    }
+    
+    public int getFormatId() {
+      return 'X';
+    }
+
+    public byte[] getBranchQualifier() {
+      return new byte[] {
+        (byte)(xid >> 0x00),
+        (byte)(xid >> 0x08)
+      };
+    }
+
+    public byte[] getGlobalTransactionId() {
+      return new byte[] {
+        (byte)(xid >> 0x10),
+        (byte)(xid >> 0x18)
+      };
+    }
+  }
+
+  /**
+   * Test the {@link DatabaseSession#create} method.
+   * As a side-effect, creates the model required by the next tests.
+   */
+  public void testSimpleOnePhaseCommit() throws URISyntaxException
+  {
+    logger.info("testSimpleOnePhaseCommit");
+
+    try {
+      DatabaseSession session = (DatabaseSession)database.newSession();
+      XAResource resource = session.getXAResource();
+      Xid xid = new TestXid(1);
+      resource.start(xid, XAResource.TMNOFLAGS);
+      try {
+        session.createModel(modelURI, null);
+        resource.end(xid, XAResource.TMSUCCESS);
+        resource.commit(xid, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  /**
+   * Test two phase commit.
+   * As a side-effect, loads the model required by the next tests.
+   */
+  public void testSimpleTwoPhaseCommit() throws URISyntaxException
+  {
+    logger.info("testSimpleTwoPhaseCommit");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      DatabaseSession session = (DatabaseSession)database.newSession();
+      XAResource resource = session.getXAResource();
+      Xid xid = new TestXid(1);
+      resource.start(xid, XAResource.TMNOFLAGS);
+      try {
+        session.setModel(modelURI, new ModelResource(fileURI));
+        resource.end(xid, XAResource.TMSUCCESS);
+        resource.prepare(xid);
+        resource.commit(xid, false);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testBasicQuery() throws URISyntaxException {
+    logger.info("Testing basicQuery");
+
+    try {
+      // Load some test data
+      DatabaseSession session = (DatabaseSession)database.newSession();
+      try {
+        XAResource resource = session.getXAResource();
+        Xid xid = new TestXid(1);
+        resource.start(xid, XAResource.TMNOFLAGS);
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer);
+        answer.close();
+
+        resource.end(xid, XAResource.TMSUCCESS);
+        resource.commit(xid, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testMultipleQuery() throws URISyntaxException {
+    logger.info("Testing MultipleQuery");
+
+    try {
+      // Load some test data
+      Session session = database.newSession();
+      XAResource resource = session.getXAResource();
+      Xid xid = new TestXid(1);
+      resource.start(xid, XAResource.TMNOFLAGS);
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer1 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        compareResults(answer1, answer2);
+
+        answer1.close();
+        answer2.close();
+
+        resource.end(xid, XAResource.TMSUCCESS);
+        resource.commit(xid, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testBasicReadOnlyQuery() throws URISyntaxException {
+    logger.info("Testing basicReadOnlyQuery");
+
+    try {
+      // Load some test data
+      DatabaseSession session = (DatabaseSession)database.newSession();
+      try {
+        XAResource resource = session.getReadOnlyXAResource();
+        Xid xid = new TestXid(1);
+        resource.start(xid, XAResource.TMNOFLAGS);
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer);
+        answer.close();
+
+        resource.end(xid, XAResource.TMSUCCESS);
+        resource.commit(xid, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testConcurrentQuery() throws URISyntaxException {
+    logger.info("Testing concurrentQuery");
+
+    try {
+      // Load some test data
+      Session session = database.newSession();
+      XAResource resource = session.getReadOnlyXAResource();
+      Xid xid1 = new TestXid(1);
+      Xid xid2 = new TestXid(2);
+      resource.start(xid1, XAResource.TMNOFLAGS);
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer1 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        resource.end(xid1, XAResource.TMSUSPEND);
+        resource.start(xid2, XAResource.TMNOFLAGS);
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        resource.end(xid2, XAResource.TMSUSPEND);
+
+        compareResults(answer1, answer2);
+
+        answer1.close();
+        answer2.close();
+
+        resource.start(xid1, XAResource.TMRESUME);
+        resource.end(xid1, XAResource.TMSUCCESS);
+        resource.end(xid2, XAResource.TMSUCCESS);
+        resource.commit(xid1, true);
+        resource.commit(xid2, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  /**
+   * Note: What this test does is a really bad idea - there is no
+   *       isolation provided as each operation is within its own
+   *       transaction.  It does however provide a good test.
+   */
+  public void testConcurrentReadWrite() throws URISyntaxException {
+    logger.info("Testing concurrentReadWrite");
+
+    try {
+      Session session = database.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      XAResource rwResource = session.getXAResource();
+      Xid xid1 = new TestXid(1);
+
+      rwResource.start(xid1, XAResource.TMNOFLAGS);
+      session.createModel(model2URI, null);
+      rwResource.end(xid1, XAResource.TMSUSPEND);
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        Xid xid2 = new TestXid(2);
+        roResource.start(xid2, XAResource.TMNOFLAGS);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        roResource.end(xid2, XAResource.TMSUSPEND);
+        answer.beforeFirst();
+        while (answer.next()) {
+          rwResource.start(xid1, XAResource.TMRESUME);
+          session.insert(model2URI, Collections.singleton(new TripleImpl(
+              (SubjectNode)answer.getObject(0),
+              (PredicateNode)answer.getObject(1),
+              (ObjectNode)answer.getObject(2))));
+          rwResource.end(xid1, XAResource.TMSUSPEND);
+        }
+        answer.close();
+
+        rwResource.end(xid1, XAResource.TMSUCCESS);
+        rwResource.commit(xid1, true);
+
+        Xid xid3 = new TestXid(3);
+        roResource.start(xid3, XAResource.TMNOFLAGS);
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model2URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        roResource.end(xid3, XAResource.TMSUSPEND);
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer2);
+        answer2.close();
+
+        Xid xid4 = new TestXid(4);
+        rwResource.start(xid4, XAResource.TMNOFLAGS);
+        session.removeModel(model2URI);
+        rwResource.end(xid4, XAResource.TMSUCCESS);
+        rwResource.commit(xid4, true);
+
+        roResource.end(xid2, XAResource.TMSUCCESS);
+        roResource.commit(xid2, true);
+        roResource.end(xid3, XAResource.TMSUCCESS);
+        roResource.commit(xid3, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testSubqueryQuery() throws URISyntaxException {
+    logger.info("Testing subqueryQuery");
+
+    try {
+      // Load some test data
+      Session session = database.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      Xid xid1 = new TestXid(1);
+      roResource.start(xid1, XAResource.TMNOFLAGS);
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(new Subquery(new Variable("k0"), new Query(
+          Collections.singletonList(objectVariable),
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(objectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        )));
+
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+              new URIReferenceImpl(new URI("test:p03")),
+              objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        roResource.end(xid1, XAResource.TMSUSPEND);
+
+        answer.beforeFirst();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s01")),
+            answer.getObject(0));
+        Answer sub1 = (Answer)answer.getObject(1);
+        compareResults(new String[][] { new String[] { "test:o01" },
+                                        new String[] { "test:o02" } }, sub1);
+        sub1.close();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s02")),
+            answer.getObject(0));
+        Answer sub2 = (Answer)answer.getObject(1);
+        compareResults(new String[][] { new String[] { "test:o02" },
+                                        new String[] { "test:o03" } }, sub2);
+        // Leave sub2 open.
+
+        assertFalse(answer.next());
+        answer.close();
+        sub2.close();
+
+        // Leave transaction to be closed on session close.
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testConcurrentSubqueryQuery() throws URISyntaxException {
+    logger.info("Testing concurrentSubqueryQuery");
+
+    try {
+      Session session = database.newSession();
+      XAResource rwResource = session.getXAResource();
+      Xid xid1 = new TestXid(1);
+      rwResource.start(xid1, XAResource.TMNOFLAGS);
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(new Subquery(new Variable("k0"), new Query(
+          Collections.singletonList(objectVariable),
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(objectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        )));
+
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+              new URIReferenceImpl(new URI("test:p03")),
+              objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        answer.beforeFirst();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s01")),
+            answer.getObject(0));
+        Answer sub1 = (Answer)answer.getObject(1);
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s02")),
+            answer.getObject(0));
+        Answer sub2 = (Answer)answer.getObject(1);
+        assertFalse(answer.next());
+
+        assertEquals(1, sub1.getNumberOfVariables());
+        assertEquals(1, sub2.getNumberOfVariables());
+        sub1.beforeFirst();
+        sub2.beforeFirst();
+        assertTrue(sub1.next());
+        assertTrue(sub2.next());
+        assertEquals(new URIReferenceImpl(new URI("test:o01")), sub1.getObject(0));
+        assertEquals(new URIReferenceImpl(new URI("test:o02")), sub2.getObject(0));
+
+        rwResource.end(xid1, XAResource.TMSUSPEND);
+
+        assertTrue(sub1.next());
+        assertTrue(sub2.next());
+        assertEquals(new URIReferenceImpl(new URI("test:o02")), sub1.getObject(0));
+        assertEquals(new URIReferenceImpl(new URI("test:o03")), sub2.getObject(0));
+        assertFalse(sub1.next());
+        assertFalse(sub2.next());
+
+        answer.close();
+
+        rwResource.end(xid1, XAResource.TMSUCCESS);
+        rwResource.commit(xid1, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testExplicitIsolationQuerySingleSession() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session = database.newSession();
+      try {
+        XAResource roResource = session.getReadOnlyXAResource();
+        XAResource rwResource = session.getXAResource();
+        Xid xid1 = new TestXid(1); // Initial create model.
+        Xid xid2 = new TestXid(2); // Started before setModel.
+        Xid xid3 = new TestXid(3); // setModel.
+        Xid xid4 = new TestXid(4); // Started before setModel prepares
+        Xid xid5 = new TestXid(5); // Started before setModel commits
+        Xid xid6 = new TestXid(6); // Started after setModel commits
+        Xid xid7 = new TestXid(7); // Final remove model.
+
+        rwResource.start(xid1, XAResource.TMNOFLAGS);
+        session.createModel(model3URI, null);
+        rwResource.end(xid1, XAResource.TMSUCCESS);
+        rwResource.commit(xid1, true);
+
+        // Nothing visible.
+        roResource.start(xid2, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Perform update
+        rwResource.start(xid3, XAResource.TMNOFLAGS);
+        session.setModel(model3URI, new ModelResource(fileURI));
+        rwResource.end(xid3, XAResource.TMSUSPEND);
+
+        // Check uncommitted change not visible
+        roResource.start(xid4, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check original phase unaffected.
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check micro-commit visible to current-phase
+        rwResource.start(xid3, XAResource.TMRESUME);
+        assertChangeVisible(session);
+        // Perform prepare
+        rwResource.end(xid3, XAResource.TMSUCCESS);
+        rwResource.prepare(xid3);
+
+        // Check original phase unaffected
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check pre-prepare phase unaffected
+        roResource.start(xid4, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check committed phase unaffected.
+        roResource.start(xid5, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid5, XAResource.TMSUSPEND);
+
+        // Do commit
+        rwResource.commit(xid3, false);
+
+        // Check original phase
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check pre-prepare
+        roResource.start(xid4, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check pre-commit
+        roResource.start(xid5, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid5, XAResource.TMSUSPEND);
+
+        // Check committed phase is now updated
+        roResource.start(xid6, XAResource.TMNOFLAGS);
+        assertChangeVisible(session);
+
+        // Cleanup transactions.
+        roResource.end(xid6, XAResource.TMSUCCESS);
+        roResource.end(xid2, XAResource.TMSUCCESS);
+        roResource.end(xid4, XAResource.TMSUCCESS);
+        roResource.end(xid5, XAResource.TMSUCCESS);
+        roResource.commit(xid2, true);
+        roResource.commit(xid4, true);
+        roResource.commit(xid5, true);
+        roResource.commit(xid6, true);
+
+        // Cleanup database
+        rwResource.start(xid7, XAResource.TMNOFLAGS);
+        session.removeModel(model3URI);
+        rwResource.end(xid7, XAResource.TMSUCCESS);
+        rwResource.commit(xid7, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testExternalInternalIsolation() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        Session session2 = database.newSession();
+        try {
+          XAResource roResource = session1.getReadOnlyXAResource();
+          XAResource rwResource = session1.getXAResource();
+          Xid xid1 = new TestXid(1); // Initial create model.
+          Xid xid2 = new TestXid(2); // Main Test.
+          Xid xid3 = new TestXid(3); // Cleanup test.
+
+          rwResource.start(xid1, XAResource.TMNOFLAGS);
+          session1.createModel(model3URI, null);
+          rwResource.end(xid1, XAResource.TMSUCCESS);
+          rwResource.commit(xid1, true);
+
+          // Nothing visible.
+          assertChangeNotVisible(session2);
+
+          // Perform update
+          rwResource.start(xid2, XAResource.TMNOFLAGS);
+          session1.setModel(model3URI, new ModelResource(fileURI));
+          rwResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check uncommitted change not visible
+          assertChangeNotVisible(session2);
+
+          // Check micro-commit visible to current-phase
+          rwResource.start(xid2, XAResource.TMRESUME);
+          assertChangeVisible(session1);
+          // Perform prepare
+          rwResource.end(xid2, XAResource.TMSUCCESS);
+          rwResource.prepare(xid2);
+
+          // Check original phase unaffected
+          assertChangeNotVisible(session2);
+
+          // Do commit
+          rwResource.commit(xid2, false);
+
+          // Check committed phase is now updated
+          assertChangeVisible(session2);
+
+          // Cleanup database
+          session2.removeModel(model3URI);
+        } finally {
+          session2.close();
+        }
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testInternalExternalIsolation() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        Session session2 = database.newSession();
+        try {
+          XAResource roResource = session2.getReadOnlyXAResource();
+          XAResource rwResource = session2.getXAResource();
+          Xid xid1 = new TestXid(1); // Pre-update
+          Xid xid2 = new TestXid(2); // Post-update/Pre-commit
+          Xid xid3 = new TestXid(3); // Post-commit
+
+          session1.createModel(model3URI, null);
+
+          // Nothing visible.
+          roResource.start(xid1, XAResource.TMNOFLAGS);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Perform update with autocommit off
+          session1.setAutoCommit(false);
+          session1.setModel(model3URI, new ModelResource(fileURI));
+
+          // Check uncommitted change not visible
+          roResource.start(xid2, XAResource.TMNOFLAGS);
+          assertChangeNotVisible(session2);
+          roResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check original phase unaffected.
+          roResource.start(xid1, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Check micro-commit visible to current-phase
+          assertChangeVisible(session1);
+          session1.setAutoCommit(true);
+
+          // Check original phase unaffected
+          roResource.start(xid1, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Check pre-commit phase unaffected
+          roResource.start(xid2, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check committed phase is now updated and write-lock available
+          rwResource.start(xid3, XAResource.TMNOFLAGS);
+          assertChangeVisible(session2);
+          
+          // Check internal transaction read-only
+          assertChangeVisible(session1);
+
+          // Cleanup transactions.
+          rwResource.end(xid3, XAResource.TMSUCCESS);
+          roResource.end(xid2, XAResource.TMSUCCESS);
+          roResource.end(xid1, XAResource.TMSUCCESS);
+          roResource.commit(xid1, true);
+          roResource.commit(xid2, true);
+          rwResource.commit(xid3, true);
+
+          // Cleanup database (check write-lock available again)
+          session1.removeModel(model3URI);
+        } finally {
+          session2.close();
+        }
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  private void assertChangeVisible(Session session) throws Exception {
+    Variable subjectVariable   = new Variable("subject");
+    Variable predicateVariable = new Variable("predicate");
+    Variable objectVariable    = new Variable("object");
+
+    List selectList = new ArrayList(3);
+    selectList.add(subjectVariable);
+    selectList.add(predicateVariable);
+    selectList.add(objectVariable);
+
+    // Evaluate the query
+    Answer answer = session.query(new Query(
+      selectList,                                       // SELECT
+      new ModelResource(model3URI),                      // FROM
+      new ConstraintImpl(subjectVariable,               // WHERE
+                     predicateVariable,
+                     objectVariable),
+      null,                                             // HAVING
+      Arrays.asList(new Order[] {                       // ORDER BY
+        new Order(subjectVariable, true),
+        new Order(predicateVariable, true),
+        new Order(objectVariable, true)
+      }),
+      null,                                             // LIMIT
+      0,                                                // OFFSET
+      new UnconstrainedAnswer()                         // GIVEN
+    ));
+
+    String[][] results = {
+      { "test:s01", "test:p01", "test:o01" },
+      { "test:s01", "test:p02", "test:o01" },
+      { "test:s01", "test:p02", "test:o02" },
+      { "test:s01", "test:p03", "test:o02" },
+      { "test:s02", "test:p03", "test:o02" },
+      { "test:s02", "test:p04", "test:o02" },
+      { "test:s02", "test:p04", "test:o03" },
+      { "test:s02", "test:p05", "test:o03" },
+      { "test:s03", "test:p01", "test:o01" },
+      { "test:s03", "test:p05", "test:o03" },
+      { "test:s03", "test:p06", "test:o01" },
+      { "test:s03", "test:p06", "test:o03" },
+    };
+    compareResults(results, answer);
+    answer.close();
+  }
+
+  private void assertChangeNotVisible(Session session) throws Exception {
+    Variable subjectVariable   = new Variable("subject");
+    Variable predicateVariable = new Variable("predicate");
+    Variable objectVariable    = new Variable("object");
+
+    List selectList = new ArrayList(3);
+    selectList.add(subjectVariable);
+    selectList.add(predicateVariable);
+    selectList.add(objectVariable);
+
+    // Evaluate the query
+    Answer answer = session.query(new Query(
+      selectList,                                       // SELECT
+      new ModelResource(model3URI),                      // FROM
+      new ConstraintImpl(subjectVariable,               // WHERE
+                     predicateVariable,
+                     objectVariable),
+      null,                                             // HAVING
+      Arrays.asList(new Order[] {                       // ORDER BY
+        new Order(subjectVariable, true),
+        new Order(predicateVariable, true),
+        new Order(objectVariable, true)
+      }),
+      null,                                             // LIMIT
+      0,                                                // OFFSET
+      new UnconstrainedAnswer()                         // GIVEN
+    ));
+    answer.beforeFirst();
+    assertFalse(answer.next());
+    answer.close();
+  }
+
+  /**
+   * Test two simultaneous, explicit transactions, in two threads. The second one should block
+   * until the first one sets auto-commit back to true.
+   */
+  public void testConcurrentExplicitTxn() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              XAResource resource2 = session2.getXAResource();
+              try {
+                resource2.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                resource2.end(new TestXid(3), XAResource.TMSUCCESS);
+                resource2.commit(new TestXid(3), true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.commit(new TestXid(2), true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  /**
+   * Test two simultaneous transactions, in two threads. The second one should block
+   * until the first one sets auto-commit back to true.
+   */
+  public void testExternalInternalConcurrentTxn() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                session2.setAutoCommit(false);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                session2.setAutoCommit(true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.commit(new TestXid(2), true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  /**
+   * Test two simultaneous transactions, in two threads. The second one should block
+   * until the first one sets auto-commit back to true.
+   */
+  public void testInternalExternalConcurrentTxn() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        session1.createModel(model3URI, null);
+
+        session1.setAutoCommit(false);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                XAResource resource = session2.getXAResource();
+                resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                resource.end(new TestXid(1), XAResource.TMSUCCESS);
+                resource.rollback(new TestXid(1));
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.commit();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.setAutoCommit(true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        session1.removeModel(model3URI);
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  /**
+   * Test two simultaneous transactions, in two threads. The second one should block
+   * until the first one sets auto-commit back to true.
+   */
+  public void testExternalInternalConcurrentTxnRollback() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                session2.setAutoCommit(false);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                answer.beforeFirst();
+                assertFalse(answer.next());
+                answer.close();
+
+                session2.setAutoCommit(true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.rollback(new TestXid(2));
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  /**
+   * Test two simultaneous transactions, in two threads. The second one should block
+   * until the first one sets auto-commit back to true.
+   */
+  public void testInternalExternalConcurrentTxnRollback() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        session1.createModel(model3URI, null);
+
+        session1.setAutoCommit(false);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                XAResource resource = session2.getXAResource();
+                resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                answer.beforeFirst();
+                assertFalse(answer.next());
+                answer.close();
+
+                resource.end(new TestXid(1), XAResource.TMFAIL);
+                resource.rollback(new TestXid(1));
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.rollback();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.setAutoCommit(true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        session1.removeModel(model3URI);
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testExplicitRollbackIsolationQuery() throws URISyntaxException {
+    logger.info("testExplicitRollbackIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session = database.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      XAResource rwResource = session.getXAResource();
+      try {
+        rwResource.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session.createModel(model3URI, null);
+        rwResource.end(new TestXid(1), XAResource.TMSUCCESS);
+        rwResource.commit(new TestXid(1), true);
+
+        rwResource.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session.setModel(model3URI, new ModelResource(fileURI));
+        rwResource.end(new TestXid(2), XAResource.TMSUSPEND);
+
+        roResource.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model3URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        answer.beforeFirst();
+        assertFalse(answer.next());
+        answer.close();
+
+        roResource.end(new TestXid(3), XAResource.TMSUCCESS);
+        roResource.commit(new TestXid(3), true);
+
+        rwResource.end(new TestXid(2), XAResource.TMFAIL);
+        rwResource.rollback(new TestXid(2));
+
+        roResource.start(new TestXid(4), XAResource.TMNOFLAGS);
+        selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model3URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        answer.beforeFirst();
+        assertFalse(answer.next());
+        answer.close();
+
+        roResource.end(new TestXid(4), XAResource.TMFAIL);
+        roResource.rollback(new TestXid(4));
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  /**
+   * Tests cleaning up a transaction on close.  This test added in the process
+   * of fixing a bug reported by Ronald on the JTA-beta.
+   */
+  public void testInternalSerialMultipleSessions() throws URISyntaxException
+  {
+    logger.info("testInternalSerialMultipleSessions");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      Session session2 = database.newSession();
+      try {
+        session1.createModel(model4URI, null);
+
+        session1.setAutoCommit(false);
+        session1.setModel(model4URI, new ModelResource(fileURI));
+
+        session1.commit();
+        session1.close();
+
+        session2.setAutoCommit(false);
+      } finally {
+        session2.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  //
+  // Internal methods
+  //
+
+  private void compareResults(String[][] expected, Answer answer) throws Exception {
+    try {
+      answer.beforeFirst();
+      for (int i = 0; i < expected.length; i++) {
+        assertTrue("Answer short at row " + i, answer.next());
+        assertEquals(expected[i].length, answer.getNumberOfVariables());
+        for (int j = 0; j < expected[i].length; j++) {
+          URIReferenceImpl uri = new URIReferenceImpl(new URI(expected[i][j]));
+          assertEquals(uri, answer.getObject(j));
+        }
+      }
+      assertFalse(answer.next());
+    } catch (Exception e) {
+      logger.error("Failed test - " + answer);
+      answer.close();
+      throw e;
+    }
+  }
+
+  private void compareResults(Answer answer1, Answer answer2) throws Exception {
+    answer1.beforeFirst();
+    answer2.beforeFirst();
+    assertEquals(answer1.getNumberOfVariables(), answer2.getNumberOfVariables());
+    while (answer1.next()) {
+      assertTrue(answer2.next());
+      for (int i = 0; i < answer1.getNumberOfVariables(); i++) {
+        assertEquals(answer1.getObject(i), answer2.getObject(i));
+      }
+    }
+    assertFalse(answer2.next());
+  }
+
+
+  /**
+   * Fail with an unexpected exception
+   */
+  private void fail(Throwable throwable)
+  {
+    StringWriter stringWriter = new StringWriter();
+    throwable.printStackTrace(new PrintWriter(stringWriter));
+    fail(stringWriter.toString());
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/InternalResolver.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/InternalResolver.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/InternalResolver.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -126,6 +126,14 @@
                    Resolver        systemResolver)
     throws ResolverFactoryException
   {
+    if (resolver == null) {
+      throw new IllegalArgumentException("Resolver 'null'");
+    } else if (resolverSession == null) {
+      throw new IllegalArgumentException("ResolverSession 'null'");
+    } else if (systemResolver == null) {
+      throw new IllegalArgumentException("SystemResolver 'null'");
+    }
+
     // Initialize fields
     this.resolver        = resolver;
     this.rdfType         = rdfType;

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/JotmTransactionStandaloneTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,2114 @@
+/*
+ * Copyright 2008 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.resolver;
+
+// Java 2 standard packages
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+// Third party packages
+import junit.framework.*;        // JUnit
+import org.apache.log4j.Logger;  // Log4J
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
+import org.objectweb.jotm.Jotm;
+import org.objectweb.transaction.jta.TMService;
+
+// Locally written packages
+import org.mulgara.query.*;
+import org.mulgara.query.rdf.Mulgara;
+import org.mulgara.query.rdf.URIReferenceImpl;
+import org.mulgara.query.rdf.TripleImpl;
+import org.mulgara.server.Session;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
+import org.mulgara.util.FileUtil;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.server.JRDFSession;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
+
+/**
+ * Regression test to test JTA integration with external JOTM instance.
+ *
+ * @created 2008-01-11
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ * @copyright &copy;2008 <a href="http://www.topazproject.org/">The Topaz Foundation</a>
+ * @licence Apache License v2.0
+ */
+public class JotmTransactionStandaloneTest extends TestCase
+{
+  /** Logger.  */
+  private static Logger logger =
+    Logger.getLogger(JotmTransactionStandaloneTest.class.getName());
+
+  private static final URI databaseURI;
+
+  private static final URI systemModelURI;
+
+  private static final URI modelURI;
+  private static final URI model2URI;
+  private static final URI model3URI;
+  private static final URI model4URI;
+  private static final URI model5URI;
+
+  static {
+    try {
+      databaseURI    = new URI("rmi://localhost/server1");
+      systemModelURI = new URI("rmi://localhost/server1#");
+      modelURI       = new URI("rmi://localhost/server1#jotmmodel");
+      model2URI      = new URI("rmi://localhost/server1#jotmmodel2");
+      model3URI      = new URI("rmi://localhost/server1#jotmmodel3");
+      model4URI      = new URI("rmi://localhost/server1#jotmmodel4");
+      model5URI      = new URI("rmi://localhost/server1#jotmmodel5");
+    } catch (URISyntaxException e) {
+      throw new Error("Bad hardcoded URI", e);
+    }
+  }
+
+  private static SessionFactory sessionFactory;
+  private static TMService txService;
+  private static TransactionManager txManager;
+
+  public JotmTransactionStandaloneTest(String name) {
+    super(name);
+  }
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTest(new JotmTransactionStandaloneTest("setup"));
+    suite.addTest(new JotmTransactionStandaloneTest("testTrivalExplicit"));
+    suite.addTest(new JotmTransactionStandaloneTest("testSessionCloseRollback"));
+    suite.addTest(new JotmTransactionStandaloneTest("testTrivialExplicitAgain"));
+    suite.addTest(new JotmTransactionStandaloneTest("testBasicQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testMultipleEnlist"));
+    suite.addTest(new JotmTransactionStandaloneTest("testMultipleQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testBasicReadOnlyQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testConcurrentQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testRepeatGetXAQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testConcurrentReadWrite"));
+    suite.addTest(new JotmTransactionStandaloneTest("testSubqueryQuery"));
+    suite.addTest(new JotmTransactionStandaloneTest("testTrivalImplicit"));
+    suite.addTest(new JotmTransactionStandaloneTest("cleanup"));
+
+    return suite;
+  }
+
+
+  public void setup() throws Exception {
+    logger.info("Doing setup");
+    sessionFactory = SessionFactoryFinder.newSessionFactory(databaseURI);
+    txService = new Jotm(true, false); // local, unbound.
+    txManager = txService.getTransactionManager();
+  }
+
+  public void cleanup() throws Exception {
+    logger.info("Doing cleanup");
+    txService.stop();
+  }
+
+  //
+  // Test cases
+  //
+
+  private static class TestXid implements Xid {
+    private int xid;
+    public TestXid(int xid) {
+      this.xid = xid;
+    }
+    
+    public int getFormatId() {
+      return 'X';
+    }
+
+    public byte[] getBranchQualifier() {
+      return new byte[] {
+        (byte)(xid >> 0x00),
+        (byte)(xid >> 0x08)
+      };
+    }
+
+    public byte[] getGlobalTransactionId() {
+      return new byte[] {
+        (byte)(xid >> 0x10),
+        (byte)(xid >> 0x18)
+      };
+    }
+  }
+
+  /**
+   * Test the {@link DatabaseSession#create} method.
+   * As a side-effect, creates the model required by the next tests.
+   */
+  public void testTrivalExplicit() throws URISyntaxException {
+    logger.info("testTrivalExplicit");
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      txManager.getTransaction().enlistResource(session.getXAResource());
+
+      try {
+        session.createModel(modelURI, null);
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testSessionCloseRollback() throws URISyntaxException {
+    logger.info("testSessionCloseRollback");
+    try {
+      URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      txManager.getTransaction().enlistResource(session.getXAResource());
+
+      try {
+        try {
+          session.setModel(modelURI, new ModelResource(fileURI));
+        } finally {
+          session.close();
+        }
+      } finally {
+        try {
+          txManager.commit();
+        } catch (HeuristicRollbackException eh) { // This is my expectation.
+          logger.warn("HeuristicRollback detected successfully", eh);
+        } catch (RollbackException er) {          // This would also meet the spec.
+          logger.warn("Rollback detected successfully", er);
+        } catch (Exception e) {
+          logger.warn("Exception from Jotm", e);
+          throw e;
+        }
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testTrivialExplicitAgain() throws URISyntaxException {
+    logger.info("testTrivialExplicitAgain");
+    try {
+      URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      txManager.getTransaction().enlistResource(session.getXAResource());
+
+      try {
+        session.setModel(modelURI, new ModelResource(fileURI));
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testBasicQuery() throws URISyntaxException {
+    logger.info("testBasicQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      try {
+        txManager.getTransaction().enlistResource(session.getXAResource());
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer);
+        answer.close();
+
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testMultipleEnlist() throws URISyntaxException {
+    logger.info("testMultipleEnlist");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      try {
+        txManager.getTransaction().enlistResource(session.getXAResource());
+        txManager.getTransaction().enlistResource(session.getXAResource());
+        txManager.getTransaction().enlistResource(session.getXAResource());
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer);
+        answer.close();
+
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testMultipleQuery() throws URISyntaxException {
+    logger.info("testMultipleQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      txManager.getTransaction().enlistResource(session.getXAResource());
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer1 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        compareResults(answer1, answer2);
+
+        answer1.close();
+        answer2.close();
+
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testBasicReadOnlyQuery() throws URISyntaxException {
+    logger.info("testBasicReadOnlyQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      try {
+        txManager.getTransaction().enlistResource(session.getReadOnlyXAResource());
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer);
+        answer.close();
+
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testConcurrentQuery() throws URISyntaxException {
+    logger.info("testConcurrentQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      Transaction tx1 = txManager.getTransaction();
+      tx1.enlistResource(roResource);
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer1 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        
+        tx1 = txManager.suspend();
+
+        txManager.begin();
+        Transaction tx2 = txManager.getTransaction();
+        tx2.enlistResource(roResource);
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        tx2 = txManager.suspend();
+
+        compareResults(answer1, answer2);
+
+        answer1.close();
+        answer2.close();
+
+        txManager.resume(tx1);
+        txManager.commit();
+        // I believe JTA requires me to call end here - our implementation doesn't care.
+        tx2.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testRepeatGetXAQuery() throws URISyntaxException {
+    logger.info("testRepeatGetXAQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      Transaction tx1 = txManager.getTransaction();
+      tx1.enlistResource(session.getReadOnlyXAResource());
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer1 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        
+        tx1 = txManager.suspend();
+
+        txManager.begin();
+        Transaction tx2 = txManager.getTransaction();
+        tx2.enlistResource(session.getReadOnlyXAResource());
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        tx2 = txManager.suspend();
+
+        compareResults(answer1, answer2);
+
+        answer1.close();
+        answer2.close();
+
+        txManager.resume(tx1);
+        txManager.commit();
+        // I believe JTA requires me to call end here - our implementation doesn't care.
+        tx2.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  //
+  // Note: What this test does is a really bad idea - there is no
+  //       isolation provided as each operation is within its own
+  //       transaction.  It does however provide a good test.
+  //
+  public void testConcurrentReadWrite() throws URISyntaxException {
+    logger.info("testConcurrentReadWrite");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      XAResource rwResource = session.getXAResource();
+
+      txManager.getTransaction().enlistResource(rwResource);
+      session.createModel(model2URI, null);
+      Transaction tx1 = txManager.suspend();
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        txManager.begin();
+        txManager.getTransaction().enlistResource(roResource);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        Transaction tx2 = txManager.suspend();
+
+        answer.beforeFirst();
+        while (answer.next()) {
+          txManager.resume(tx1);
+          session.insert(model2URI, Collections.singleton(new TripleImpl(
+              (SubjectNode)answer.getObject(0),
+              (PredicateNode)answer.getObject(1),
+              (ObjectNode)answer.getObject(2))));
+          tx1 = txManager.suspend();
+        }
+        answer.close();
+
+        txManager.resume(tx1);
+        txManager.commit();
+
+        txManager.begin();
+        txManager.getTransaction().enlistResource(roResource);
+
+        Answer answer2 = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model2URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        Transaction tx3 = txManager.suspend();
+
+        String[][] results = {
+          { "test:s01", "test:p01", "test:o01" },
+          { "test:s01", "test:p02", "test:o01" },
+          { "test:s01", "test:p02", "test:o02" },
+          { "test:s01", "test:p03", "test:o02" },
+          { "test:s02", "test:p03", "test:o02" },
+          { "test:s02", "test:p04", "test:o02" },
+          { "test:s02", "test:p04", "test:o03" },
+          { "test:s02", "test:p05", "test:o03" },
+          { "test:s03", "test:p01", "test:o01" },
+          { "test:s03", "test:p05", "test:o03" },
+          { "test:s03", "test:p06", "test:o01" },
+          { "test:s03", "test:p06", "test:o03" },
+        };
+        compareResults(results, answer2);
+        answer2.close();
+
+        txManager.begin();
+        txManager.getTransaction().enlistResource(rwResource);
+        session.removeModel(model2URI);
+        txManager.commit();
+
+        txManager.resume(tx2);
+        txManager.commit();
+        txManager.resume(tx3);
+        txManager.commit();
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testSubqueryQuery() throws URISyntaxException {
+    logger.info("testSubqueryQuery");
+
+    try {
+      txManager.begin();
+      Session session = sessionFactory.newSession();
+      txManager.getTransaction().enlistResource(session.getReadOnlyXAResource());
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(new Subquery(new Variable("k0"), new Query(
+          Collections.singletonList(objectVariable),
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(objectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        )));
+
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+              new URIReferenceImpl(new URI("test:p03")),
+              objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        Transaction tx1 = txManager.suspend();
+
+        answer.beforeFirst();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s01")),
+            answer.getObject(0));
+        Answer sub1 = (Answer)answer.getObject(1);
+        compareResults(new String[][] { new String[] { "test:o01" },
+                                        new String[] { "test:o02" } }, sub1);
+        sub1.close();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s02")),
+            answer.getObject(0));
+        Answer sub2 = (Answer)answer.getObject(1);
+        compareResults(new String[][] { new String[] { "test:o02" },
+                                        new String[] { "test:o03" } }, sub2);
+        // Leave sub2 open.
+
+        assertFalse(answer.next());
+        answer.close();
+        sub2.close();
+
+        // Leave transaction to be closed on session close.
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+/*
+
+  public void testConcurrentSubqueryQuery() throws URISyntaxException {
+    logger.info("testConcurrentSubqueryQuery");
+
+    try {
+      Session session = database.newSession();
+      XAResource rwResource = session.getXAResource();
+      Xid xid1 = new TestXid(1);
+      rwResource.start(xid1, XAResource.TMNOFLAGS);
+
+      try {
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(new Subquery(new Variable("k0"), new Query(
+          Collections.singletonList(objectVariable),
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(objectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        )));
+
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(modelURI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+              new URIReferenceImpl(new URI("test:p03")),
+              objectVariable),
+          null,                                             // HAVING
+          Collections.singletonList(                        // ORDER BY
+            new Order(subjectVariable, true)
+          ),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        answer.beforeFirst();
+
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s01")),
+            answer.getObject(0));
+        Answer sub1 = (Answer)answer.getObject(1);
+        assertTrue(answer.next());
+        assertEquals(new URIReferenceImpl(new URI("test:s02")),
+            answer.getObject(0));
+        Answer sub2 = (Answer)answer.getObject(1);
+        assertFalse(answer.next());
+
+        assertEquals(1, sub1.getNumberOfVariables());
+        assertEquals(1, sub2.getNumberOfVariables());
+        sub1.beforeFirst();
+        sub2.beforeFirst();
+        assertTrue(sub1.next());
+        assertTrue(sub2.next());
+        assertEquals(new URIReferenceImpl(new URI("test:o01")), sub1.getObject(0));
+        assertEquals(new URIReferenceImpl(new URI("test:o02")), sub2.getObject(0));
+
+        rwResource.end(xid1, XAResource.TMSUSPEND);
+
+        assertTrue(sub1.next());
+        assertTrue(sub2.next());
+        assertEquals(new URIReferenceImpl(new URI("test:o02")), sub1.getObject(0));
+        assertEquals(new URIReferenceImpl(new URI("test:o03")), sub2.getObject(0));
+        assertFalse(sub1.next());
+        assertFalse(sub2.next());
+
+        answer.close();
+
+        rwResource.end(xid1, XAResource.TMSUCCESS);
+        rwResource.commit(xid1, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testExplicitIsolationQuerySingleSession() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session = database.newSession();
+      try {
+        XAResource roResource = session.getReadOnlyXAResource();
+        XAResource rwResource = session.getXAResource();
+        Xid xid1 = new TestXid(1); // Initial create model.
+        Xid xid2 = new TestXid(2); // Started before setModel.
+        Xid xid3 = new TestXid(3); // setModel.
+        Xid xid4 = new TestXid(4); // Started before setModel prepares
+        Xid xid5 = new TestXid(5); // Started before setModel commits
+        Xid xid6 = new TestXid(6); // Started after setModel commits
+        Xid xid7 = new TestXid(7); // Final remove model.
+
+        rwResource.start(xid1, XAResource.TMNOFLAGS);
+        session.createModel(model3URI, null);
+        rwResource.end(xid1, XAResource.TMSUCCESS);
+        rwResource.commit(xid1, true);
+
+        // Nothing visible.
+        roResource.start(xid2, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Perform update
+        rwResource.start(xid3, XAResource.TMNOFLAGS);
+        session.setModel(model3URI, new ModelResource(fileURI));
+        rwResource.end(xid3, XAResource.TMSUSPEND);
+
+        // Check uncommitted change not visible
+        roResource.start(xid4, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check original phase unaffected.
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check micro-commit visible to current-phase
+        rwResource.start(xid3, XAResource.TMRESUME);
+        assertChangeVisible(session);
+        // Perform prepare
+        rwResource.end(xid3, XAResource.TMSUCCESS);
+        rwResource.prepare(xid3);
+
+        // Check original phase unaffected
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check pre-prepare phase unaffected
+        roResource.start(xid4, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check committed phase unaffected.
+        roResource.start(xid5, XAResource.TMNOFLAGS);
+        assertChangeNotVisible(session);
+        roResource.end(xid5, XAResource.TMSUSPEND);
+
+        // Do commit
+        rwResource.commit(xid3, false);
+
+        // Check original phase
+        roResource.start(xid2, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid2, XAResource.TMSUSPEND);
+
+        // Check pre-prepare
+        roResource.start(xid4, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid4, XAResource.TMSUSPEND);
+
+        // Check pre-commit
+        roResource.start(xid5, XAResource.TMRESUME);
+        assertChangeNotVisible(session);
+        roResource.end(xid5, XAResource.TMSUSPEND);
+
+        // Check committed phase is now updated
+        roResource.start(xid6, XAResource.TMNOFLAGS);
+        assertChangeVisible(session);
+
+        // Cleanup transactions.
+        roResource.end(xid6, XAResource.TMSUCCESS);
+        roResource.end(xid2, XAResource.TMSUCCESS);
+        roResource.end(xid4, XAResource.TMSUCCESS);
+        roResource.end(xid5, XAResource.TMSUCCESS);
+        roResource.commit(xid2, true);
+        roResource.commit(xid4, true);
+        roResource.commit(xid5, true);
+        roResource.commit(xid6, true);
+
+        // Cleanup database
+        rwResource.start(xid7, XAResource.TMNOFLAGS);
+        session.removeModel(model3URI);
+        rwResource.end(xid7, XAResource.TMSUCCESS);
+        rwResource.commit(xid7, true);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testExternalInternalIsolation() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        Session session2 = database.newSession();
+        try {
+          XAResource roResource = session1.getReadOnlyXAResource();
+          XAResource rwResource = session1.getXAResource();
+          Xid xid1 = new TestXid(1); // Initial create model.
+          Xid xid2 = new TestXid(2); // Main Test.
+          Xid xid3 = new TestXid(3); // Cleanup test.
+
+          rwResource.start(xid1, XAResource.TMNOFLAGS);
+          session1.createModel(model3URI, null);
+          rwResource.end(xid1, XAResource.TMSUCCESS);
+          rwResource.commit(xid1, true);
+
+          // Nothing visible.
+          assertChangeNotVisible(session2);
+
+          // Perform update
+          rwResource.start(xid2, XAResource.TMNOFLAGS);
+          session1.setModel(model3URI, new ModelResource(fileURI));
+          rwResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check uncommitted change not visible
+          assertChangeNotVisible(session2);
+
+          // Check micro-commit visible to current-phase
+          rwResource.start(xid2, XAResource.TMRESUME);
+          assertChangeVisible(session1);
+          // Perform prepare
+          rwResource.end(xid2, XAResource.TMSUCCESS);
+          rwResource.prepare(xid2);
+
+          // Check original phase unaffected
+          assertChangeNotVisible(session2);
+
+          // Do commit
+          rwResource.commit(xid2, false);
+
+          // Check committed phase is now updated
+          assertChangeVisible(session2);
+
+          // Cleanup database
+          session2.removeModel(model3URI);
+        } finally {
+          session2.close();
+        }
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  public void testInternalExternalIsolation() throws URISyntaxException
+  {
+    logger.info("testExplicitIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        Session session2 = database.newSession();
+        try {
+          XAResource roResource = session2.getReadOnlyXAResource();
+          XAResource rwResource = session2.getXAResource();
+          Xid xid1 = new TestXid(1); // Pre-update
+          Xid xid2 = new TestXid(2); // Post-update/Pre-commit
+          Xid xid3 = new TestXid(3); // Post-commit
+
+          session1.createModel(model3URI, null);
+
+          // Nothing visible.
+          roResource.start(xid1, XAResource.TMNOFLAGS);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Perform update with autocommit off
+          session1.setAutoCommit(false);
+          session1.setModel(model3URI, new ModelResource(fileURI));
+
+          // Check uncommitted change not visible
+          roResource.start(xid2, XAResource.TMNOFLAGS);
+          assertChangeNotVisible(session2);
+          roResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check original phase unaffected.
+          roResource.start(xid1, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Check micro-commit visible to current-phase
+          assertChangeVisible(session1);
+          session1.setAutoCommit(true);
+
+          // Check original phase unaffected
+          roResource.start(xid1, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid1, XAResource.TMSUSPEND);
+
+          // Check pre-commit phase unaffected
+          roResource.start(xid2, XAResource.TMRESUME);
+          assertChangeNotVisible(session2);
+          roResource.end(xid2, XAResource.TMSUSPEND);
+
+          // Check committed phase is now updated and write-lock available
+          rwResource.start(xid3, XAResource.TMNOFLAGS);
+          assertChangeVisible(session2);
+          
+          // Check internal transaction read-only
+          assertChangeVisible(session1);
+
+          // Cleanup transactions.
+          rwResource.end(xid3, XAResource.TMSUCCESS);
+          roResource.end(xid2, XAResource.TMSUCCESS);
+          roResource.end(xid1, XAResource.TMSUCCESS);
+          roResource.commit(xid1, true);
+          roResource.commit(xid2, true);
+          rwResource.commit(xid3, true);
+
+          // Cleanup database (check write-lock available again)
+          session1.removeModel(model3URI);
+        } finally {
+          session2.close();
+        }
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  private void assertChangeVisible(Session session) throws Exception {
+    Variable subjectVariable   = new Variable("subject");
+    Variable predicateVariable = new Variable("predicate");
+    Variable objectVariable    = new Variable("object");
+
+    List selectList = new ArrayList(3);
+    selectList.add(subjectVariable);
+    selectList.add(predicateVariable);
+    selectList.add(objectVariable);
+
+    // Evaluate the query
+    Answer answer = session.query(new Query(
+      selectList,                                       // SELECT
+      new ModelResource(model3URI),                      // FROM
+      new ConstraintImpl(subjectVariable,               // WHERE
+                     predicateVariable,
+                     objectVariable),
+      null,                                             // HAVING
+      Arrays.asList(new Order[] {                       // ORDER BY
+        new Order(subjectVariable, true),
+        new Order(predicateVariable, true),
+        new Order(objectVariable, true)
+      }),
+      null,                                             // LIMIT
+      0,                                                // OFFSET
+      new UnconstrainedAnswer()                         // GIVEN
+    ));
+
+    String[][] results = {
+      { "test:s01", "test:p01", "test:o01" },
+      { "test:s01", "test:p02", "test:o01" },
+      { "test:s01", "test:p02", "test:o02" },
+      { "test:s01", "test:p03", "test:o02" },
+      { "test:s02", "test:p03", "test:o02" },
+      { "test:s02", "test:p04", "test:o02" },
+      { "test:s02", "test:p04", "test:o03" },
+      { "test:s02", "test:p05", "test:o03" },
+      { "test:s03", "test:p01", "test:o01" },
+      { "test:s03", "test:p05", "test:o03" },
+      { "test:s03", "test:p06", "test:o01" },
+      { "test:s03", "test:p06", "test:o03" },
+    };
+    compareResults(results, answer);
+    answer.close();
+  }
+
+  private void assertChangeNotVisible(Session session) throws Exception {
+    Variable subjectVariable   = new Variable("subject");
+    Variable predicateVariable = new Variable("predicate");
+    Variable objectVariable    = new Variable("object");
+
+    List selectList = new ArrayList(3);
+    selectList.add(subjectVariable);
+    selectList.add(predicateVariable);
+    selectList.add(objectVariable);
+
+    // Evaluate the query
+    Answer answer = session.query(new Query(
+      selectList,                                       // SELECT
+      new ModelResource(model3URI),                      // FROM
+      new ConstraintImpl(subjectVariable,               // WHERE
+                     predicateVariable,
+                     objectVariable),
+      null,                                             // HAVING
+      Arrays.asList(new Order[] {                       // ORDER BY
+        new Order(subjectVariable, true),
+        new Order(predicateVariable, true),
+        new Order(objectVariable, true)
+      }),
+      null,                                             // LIMIT
+      0,                                                // OFFSET
+      new UnconstrainedAnswer()                         // GIVEN
+    ));
+    answer.beforeFirst();
+    assertFalse(answer.next());
+    answer.close();
+  }
+
+  //
+  // Test two simultaneous, explicit transactions, in two threads. The second one should block
+  // until the first one sets auto-commit back to true.
+  //
+  public void testConcurrentExplicitTxn() throws URISyntaxException
+  {
+    logger.info("testConcurrentExplicitTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              XAResource resource2 = session2.getXAResource();
+              try {
+                resource2.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                resource2.end(new TestXid(3), XAResource.TMSUCCESS);
+                resource2.commit(new TestXid(3), true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.commit(new TestXid(2), true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  //*
+  // Test two simultaneous transactions, in two threads. The second one should block
+  // until the first one sets auto-commit back to true.
+  ///
+  public void testExternalInternalConcurrentTxn() throws URISyntaxException
+  {
+    logger.info("testExternalInternalConcurrentTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                session2.setAutoCommit(false);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                session2.setAutoCommit(true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.commit(new TestXid(2), true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  //*
+  // Test two simultaneous transactions, in two threads. The second one should block
+  // until the first one sets auto-commit back to true.
+  ///
+  public void testInternalExternalConcurrentTxn() throws URISyntaxException
+  {
+    logger.info("testInternalExternalConcurrentTxn");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        session1.createModel(model3URI, null);
+
+        session1.setAutoCommit(false);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                XAResource resource = session2.getXAResource();
+                resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                String[][] results = {
+                  { "test:s01", "test:p01", "test:o01" },
+                  { "test:s01", "test:p02", "test:o01" },
+                  { "test:s01", "test:p02", "test:o02" },
+                  { "test:s01", "test:p03", "test:o02" },
+                  { "test:s02", "test:p03", "test:o02" },
+                  { "test:s02", "test:p04", "test:o02" },
+                  { "test:s02", "test:p04", "test:o03" },
+                  { "test:s02", "test:p05", "test:o03" },
+                  { "test:s03", "test:p01", "test:o01" },
+                  { "test:s03", "test:p05", "test:o03" },
+                  { "test:s03", "test:p06", "test:o01" },
+                  { "test:s03", "test:p06", "test:o03" },
+                };
+                compareResults(results, answer);
+                answer.close();
+
+                resource.end(new TestXid(1), XAResource.TMSUCCESS);
+                resource.rollback(new TestXid(1));
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.commit();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.setAutoCommit(true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        session1.removeModel(model3URI);
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  //*
+  // Test two simultaneous transactions, in two threads. The second one should block
+  // until the first one sets auto-commit back to true.
+  ///
+  public void testExternalInternalConcurrentTxnRollback() throws URISyntaxException
+  {
+    logger.info("testExternalInternalConcurrentTxnRollback");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        XAResource resource1 = session1.getXAResource();
+        resource1.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session1.createModel(model3URI, null);
+        resource1.end(new TestXid(1), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(1), true);
+
+        resource1.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                session2.setAutoCommit(false);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                answer.beforeFirst();
+                assertFalse(answer.next());
+                answer.close();
+
+                session2.setAutoCommit(true);
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        resource1.rollback(new TestXid(2));
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        resource1.start(new TestXid(4), XAResource.TMNOFLAGS);
+        session1.removeModel(model3URI);
+        resource1.end(new TestXid(4), XAResource.TMSUCCESS);
+        resource1.commit(new TestXid(4), true);
+
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  //*
+  // Test two simultaneous transactions, in two threads. The second one should block
+  // until the first one sets auto-commit back to true.
+  ///
+  public void testInternalExternalConcurrentTxnRollback() throws URISyntaxException
+  {
+    logger.info("testInternalExternalConcurrentTxnRollback");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session1 = database.newSession();
+      try {
+        session1.createModel(model3URI, null);
+
+        session1.setAutoCommit(false);
+        session1.setModel(model3URI, new ModelResource(fileURI));
+
+        final boolean[] tx2Started = new boolean[] { false };
+
+        Thread t2 = new Thread("tx2Test") {
+          public void run() {
+            try {
+              Session session2 = database.newSession();
+              try {
+                XAResource resource = session2.getXAResource();
+                resource.start(new TestXid(1), XAResource.TMNOFLAGS);
+
+                synchronized (tx2Started) {
+                  tx2Started[0] = true;
+                  tx2Started.notify();
+                }
+
+                Variable subjectVariable   = new Variable("subject");
+                Variable predicateVariable = new Variable("predicate");
+                Variable objectVariable    = new Variable("object");
+
+                List selectList = new ArrayList(3);
+                selectList.add(subjectVariable);
+                selectList.add(predicateVariable);
+                selectList.add(objectVariable);
+
+                // Evaluate the query
+                Answer answer = session2.query(new Query(
+                  selectList,                                       // SELECT
+                  new ModelResource(model3URI),                      // FROM
+                  new ConstraintImpl(subjectVariable,               // WHERE
+                                 predicateVariable,
+                                 objectVariable),
+                  null,                                             // HAVING
+                  Arrays.asList(new Order[] {                       // ORDER BY
+                    new Order(subjectVariable, true),
+                    new Order(predicateVariable, true),
+                    new Order(objectVariable, true)
+                  }),
+                  null,                                             // LIMIT
+                  0,                                                // OFFSET
+                  new UnconstrainedAnswer()                         // GIVEN
+                ));
+
+                answer.beforeFirst();
+                assertFalse(answer.next());
+                answer.close();
+
+                resource.end(new TestXid(1), XAResource.TMFAIL);
+                resource.rollback(new TestXid(1));
+              } finally {
+                session2.close();
+              }
+            } catch (Exception e) {
+              fail(e);
+            }
+          }
+        };
+        t2.start();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.rollback();
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+          }
+          assertFalse("second transaction should still be waiting for write lock", tx2Started[0]);
+        }
+
+        session1.setAutoCommit(true);
+
+        synchronized (tx2Started) {
+          if (!tx2Started[0]) {
+            try {
+              tx2Started.wait(2000L);
+            } catch (InterruptedException ie) {
+              logger.error("wait for tx2-started interrupted", ie);
+              fail(ie);
+            }
+            assertTrue("second transaction should've started", tx2Started[0]);
+          }
+        }
+
+        try {
+          t2.join(2000L);
+        } catch (InterruptedException ie) {
+          logger.error("wait for tx2-terminated interrupted", ie);
+          fail(ie);
+        }
+        assertFalse("second transaction should've terminated", t2.isAlive());
+
+        session1.removeModel(model3URI);
+      } finally {
+        session1.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+
+  public void testExplicitRollbackIsolationQuery() throws URISyntaxException {
+    logger.info("testExplicitRollbackIsolationQuery");
+    URI fileURI  = new File("data/xatest-model1.rdf").toURI();
+
+    try {
+      Session session = database.newSession();
+      XAResource roResource = session.getReadOnlyXAResource();
+      XAResource rwResource = session.getXAResource();
+      try {
+        rwResource.start(new TestXid(1), XAResource.TMNOFLAGS);
+        session.createModel(model3URI, null);
+        rwResource.end(new TestXid(1), XAResource.TMSUCCESS);
+        rwResource.commit(new TestXid(1), true);
+
+        rwResource.start(new TestXid(2), XAResource.TMNOFLAGS);
+        session.setModel(model3URI, new ModelResource(fileURI));
+        rwResource.end(new TestXid(2), XAResource.TMSUSPEND);
+
+        roResource.start(new TestXid(3), XAResource.TMNOFLAGS);
+
+        Variable subjectVariable   = new Variable("subject");
+        Variable predicateVariable = new Variable("predicate");
+        Variable objectVariable    = new Variable("object");
+
+        List selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        Answer answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model3URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+        answer.beforeFirst();
+        assertFalse(answer.next());
+        answer.close();
+
+        roResource.end(new TestXid(3), XAResource.TMSUCCESS);
+        roResource.commit(new TestXid(3), true);
+
+        rwResource.end(new TestXid(2), XAResource.TMFAIL);
+        rwResource.rollback(new TestXid(2));
+
+        roResource.start(new TestXid(4), XAResource.TMNOFLAGS);
+        selectList = new ArrayList(3);
+        selectList.add(subjectVariable);
+        selectList.add(predicateVariable);
+        selectList.add(objectVariable);
+
+        // Evaluate the query
+        answer = session.query(new Query(
+          selectList,                                       // SELECT
+          new ModelResource(model3URI),                      // FROM
+          new ConstraintImpl(subjectVariable,               // WHERE
+                         predicateVariable,
+                         objectVariable),
+          null,                                             // HAVING
+          Arrays.asList(new Order[] {                       // ORDER BY
+            new Order(subjectVariable, true),
+            new Order(predicateVariable, true),
+            new Order(objectVariable, true)
+          }),
+          null,                                             // LIMIT
+          0,                                                // OFFSET
+          new UnconstrainedAnswer()                         // GIVEN
+        ));
+
+        answer.beforeFirst();
+        assertFalse(answer.next());
+        answer.close();
+
+        roResource.end(new TestXid(4), XAResource.TMFAIL);
+        roResource.rollback(new TestXid(4));
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+*/
+
+  public void testTrivalImplicit() throws URISyntaxException
+  {
+    logger.info("testTrivialImplicit");
+    try {
+      Session session = sessionFactory.newSession();
+
+      try {
+        session.removeModel(modelURI);
+      } finally {
+        session.close();
+      }
+    } catch (Exception e) {
+      fail(e);
+    }
+  }
+
+  //
+  // Internal methods
+  //
+
+  private void compareResults(String[][] expected, Answer answer) throws Exception {
+    try {
+      answer.beforeFirst();
+      for (int i = 0; i < expected.length; i++) {
+        assertTrue("Answer short at row " + i, answer.next());
+        assertEquals(expected[i].length, answer.getNumberOfVariables());
+        for (int j = 0; j < expected[i].length; j++) {
+          URIReferenceImpl uri = new URIReferenceImpl(new URI(expected[i][j]));
+          assertEquals(uri, answer.getObject(j));
+        }
+      }
+      assertFalse(answer.next());
+    } catch (Exception e) {
+      logger.info("Failed test - " + answer);
+      answer.close();
+      throw e;
+    }
+  }
+
+  private void compareResults(Answer answer1, Answer answer2) throws Exception {
+    answer1.beforeFirst();
+    answer2.beforeFirst();
+    assertEquals(answer1.getNumberOfVariables(), answer2.getNumberOfVariables());
+    while (answer1.next()) {
+      assertTrue(answer2.next());
+      for (int i = 0; i < answer1.getNumberOfVariables(); i++) {
+        assertEquals(answer1.getObject(i), answer2.getObject(i));
+      }
+    }
+    assertFalse(answer2.next());
+  }
+
+  /**
+   * Fail with an unexpected exception
+   */
+  private void fail(Throwable throwable)
+  {
+    StringWriter stringWriter = new StringWriter();
+    throwable.printStackTrace(new PrintWriter(stringWriter));
+    fail(stringWriter.toString());
+  }
+
+  private static class DummyXAResource implements XAResource {
+    public void end(Xid xid, int flags) throws XAException {}
+    public void forget(Xid xid) throws XAException {}
+    public int getTransactionTimeout() throws XAException { return 0; }
+    public int prepare(Xid xid) throws XAException { return 0; }
+    public Xid[] recover(int flag) throws XAException { return new Xid[] {}; }
+    public void rollback(Xid xid) throws XAException {}
+    public boolean setTransactionTimeout(int seconds) throws XAException { return false; }
+    public void start(Xid xid, int flags) throws XAException {}
+    public void commit(Xid xid, boolean twophase) throws XAException {}
+    public boolean isSameRM(XAResource xa) { return xa == this; }
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LocalJRDFDatabaseSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LocalJRDFDatabaseSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LocalJRDFDatabaseSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -191,7 +191,7 @@
       constraint = appendMulgaraIsConstraint(vars[2], toValue(object), constraint);
 
       Query query = new Query(
-          Arrays.asList((Object[])vars),   // variable list
+          Arrays.asList(vars),             // variable list
           new ModelResource(modelURI),     // model expression
           constraint,                      // constraint expr
           null,                            // no having

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LoginOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LoginOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/LoginOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -114,7 +114,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     if (securityDomain.equals(metadata.getSecurityDomainURI())) {

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModelExistsOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModelExistsOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModelExistsOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -63,7 +63,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     try {

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModifyModelOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModifyModelOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/ModifyModelOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -85,7 +85,7 @@
    * If this field is not <code>null</code>, {@link #query} will be
    * <code>null</code>
    */
-  private final Set<Triple> tripleSet;
+  private final Set<? extends Triple> tripleSet;
 
   /**
    * The query generating the statements whose occurence is to be modified.
@@ -112,7 +112,7 @@
    * @throws IllegalArgumentException if <var>modelURI</var> or
    *   <var>tripleSet</var> are <code>null</code>
    */
-  ModifyModelOperation(URI modelURI, Set<Triple> tripleSet, boolean insert)
+  ModifyModelOperation(URI modelURI, Set<? extends Triple> tripleSet, boolean insert)
   {
     // Validate "modelURI" parameter
     if (modelURI == null) {
@@ -180,7 +180,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     Statements statements;

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransaction.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransaction.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransaction.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransaction.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,328 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com) under contract to 
+ * Topaz Foundation. Portions created under this contract are
+ * Copyright (c) 2007 Topaz Foundation
+ * All Rights Reserved.
+ */
+package org.mulgara.resolver;
+
+// Java 2 enterprise packages
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.resolver.spi.DatabaseMetadata;
+import org.mulgara.resolver.spi.EnlistableResource;
+import org.mulgara.resolver.spi.ResolverSessionFactory;
+
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.QueryException;
+
+/**
+ * @created 2007-11-06
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <a href="mailto:mail at netymon.com">Netymon Pty Ltd</a>
+ *
+ * @copyright &copy;2007 <a href="http://www.topazproject.org/">Topaz Foundation</a>
+ *
+ * @licence Open Software License v3.0
+ */
+public class MulgaraExternalTransaction implements MulgaraTransaction {
+  private static final Logger logger =
+    Logger.getLogger(MulgaraExternalTransaction.class.getName());
+
+  private Xid xid;
+
+  private Set<EnlistableResource> enlisted;
+  private Set<EnlistableResource> prepared;
+  private Set<EnlistableResource> committed;
+  private Set<EnlistableResource> rollbacked;
+
+  private Map<EnlistableResource, XAResource> xaResources;
+
+  private MulgaraExternalTransactionFactory factory;
+  private DatabaseOperationContext context;
+
+  private boolean hRollback;
+  private int heurCode;
+  private boolean rollback;
+
+  MulgaraExternalTransaction(MulgaraExternalTransactionFactory factory, Xid xid, DatabaseOperationContext context)
+      throws QueryException {
+    this.factory = factory;
+    this.context = context;
+    this.xid = xid;
+
+    this.enlisted = new HashSet<EnlistableResource>();
+    this.prepared = new HashSet<EnlistableResource>();
+    this.committed = new HashSet<EnlistableResource>();
+    this.rollbacked = new HashSet<EnlistableResource>();
+
+    this.xaResources = new HashMap<EnlistableResource, XAResource>();
+
+    this.hRollback = false;
+    this.heurCode = 0;
+    this.rollback = false;
+
+    this.context.initiate(this);
+  }
+
+  // We ignore reference counting in external transactions
+  public void reference() throws MulgaraTransactionException {}  
+  public void dereference() throws MulgaraTransactionException {}
+
+  public MulgaraTransactionException abortTransaction(String errorMessage, Throwable cause)
+      throws MulgaraTransactionException {
+    report("abortTransaction");
+    try {
+      for (EnlistableResource resource : enlisted) {
+        try {
+          resource.abort();
+        } catch (Throwable throw_away) {}
+      }
+      for (EnlistableResource resource : prepared) {
+        try {
+          resource.abort();
+        } catch (Throwable throw_away) {}
+      }
+
+      return new MulgaraTransactionException(errorMessage, cause);
+    } finally {
+      factory.transactionComplete(this);
+    }
+  }
+
+  public void heuristicRollback(String cause) throws MulgaraTransactionException {
+    report("heuristicRollback");
+    hRollback = true;
+    try {
+      rollback(xid);
+    } catch (XAException xa) {
+      throw new MulgaraTransactionException("Failed heuristic rollback", xa);
+    } finally {
+      heurCode = heurCode == 0 ? XAException.XA_HEURRB : heurCode;
+    }
+  }
+
+  public void execute(Operation operation, DatabaseMetadata metadata) throws MulgaraTransactionException {
+    try {
+      operation.execute(context,
+                        context.getSystemResolver(),
+                        metadata);
+    } catch (Throwable th) {
+      try {
+        rollback(xid);
+      } catch (XAException ex) {
+        logger.error("Error in rollback after operation failure", ex);
+      }
+      throw new MulgaraTransactionException("Operation failed", th);
+    }
+  }
+
+  public AnswerOperationResult execute(AnswerOperation ao) throws TuplesException {
+    try {
+      ao.execute();
+      return ao.getResult();
+    } catch (Throwable th) {
+      try {
+        logger.warn("Error in answer operation triggered rollback", th);
+        rollback(xid);
+      } catch (XAException ex) {
+        logger.error("Error in rollback after answer-operation failure", ex);
+      }
+      throw new TuplesException("Request failed", th);
+    }
+  }
+
+  // FIXME: See if we can't rearrange things to allow this to be deleted.
+  public void execute(TransactionOperation to) throws MulgaraTransactionException {
+    to.execute();
+  }
+
+  public void enlist(EnlistableResource enlistable) throws MulgaraTransactionException {
+    try {
+      XAResource res = enlistable.getXAResource();
+      for (EnlistableResource eres : enlisted) {
+        if (res.isSameRM(xaResources.get(eres))) {
+          return;
+        }
+      }
+      enlisted.add(enlistable);
+      xaResources.put(enlistable, res);
+      // FIXME: We need to handle this uptodate operation properly - handle
+      // suspension or mid-prepare/commit.
+      // bringUptodate(res);
+      res.start(xid, XAResource.TMNOFLAGS);
+    } catch (XAException ex) {
+      throw new MulgaraTransactionException("Failed to enlist resource", ex);
+    }
+  }
+
+  //
+  // Methods used to manage transaction from XAResource.
+  //
+
+  void commit(Xid xid) throws XAException {
+    report("commit");
+    // FIXME: Consider the possiblity prepare failed, or was incomplete.
+    for (EnlistableResource er : prepared) {
+      xaResources.get(er).commit(xid, false);
+      committed.add(er);
+    }
+    cleanupTransaction();
+  }
+
+  boolean isHeuristicallyRollbacked() {
+    return hRollback;
+  }
+
+  boolean isHeuristicallyCommitted() {
+    return false;
+  }
+
+  int getHeuristicCode() {
+    return heurCode;
+  }
+
+  boolean isRollbacked() {
+    return rollback;
+  }
+
+  void prepare(Xid xid) throws XAException {
+    report("prepare");
+    for (EnlistableResource er : enlisted) {
+      xaResources.get(er).prepare(xid);
+      prepared.add(er);
+    }
+    // status = PREPARED; ?
+  }
+
+  /**
+   * Perform rollback.  Only throws exception if transaction is subject to
+   * Heuristic Completion.
+   */
+  void rollback(Xid xid) throws XAException {
+    report("rollback");
+    try {
+      rollback = true;
+      Map<EnlistableResource, XAException> rollbackFailed = new HashMap<EnlistableResource, XAException>();
+
+      for (EnlistableResource er : enlisted) {
+        try {
+          if (!committed.contains(er)) {
+            xaResources.get(er).rollback(xid);
+            rollbacked.add(er);
+          }
+        } catch (XAException ex) {
+          logger.error("Attempt to rollback resource failed", ex);
+          rollbackFailed.put(er, ex);
+        }
+      }
+
+      if (rollbackFailed.isEmpty()) {
+        if (committed.isEmpty()) {        // Clean failure and rollback
+          return; // SUCCESSFUL ROLLBACK - RETURN
+        } else {                          // No rollback-failure, but partial commit
+          heurCode = XAException.XA_HEURMIX;
+          throw new XAException(heurCode);
+        }
+      } else {
+        // Something went wrong - start by assuming if one committed all committed
+        heurCode = (committed.isEmpty()) ? 0 : XAException.XA_HEURCOM;
+        // Then check every rollback failure code for a contradiction to all committed.
+        for (XAException xaex : rollbackFailed.values()) {
+          switch (xaex.errorCode) {
+            case XAException.XA_HEURHAZ:  
+            case XAException.XAER_NOTA:
+            case XAException.XAER_RMERR:
+            case XAException.XAER_RMFAIL:
+            case XAException.XAER_INVAL:
+            case XAException.XAER_PROTO:
+              // All these amount to not knowing the result - so we have a hazard
+              // unless we already know we have a mixed result.
+              if (heurCode != XAException.XA_HEURMIX) {
+                heurCode = XAException.XA_HEURHAZ;
+              }
+              break;
+            case XAException.XA_HEURCOM:
+              if (!rollbacked.isEmpty() || heurCode == XAException.XA_HEURRB) {
+                // We know something else was rollbacked, so we know we have a mixed result.
+                heurCode = XAException.XA_HEURMIX;
+              } else if (heurCode == 0) {
+                heurCode = XAException.XA_HEURCOM;
+              } // else it's a HEURHAZ or a HEURCOM and stays that way.
+              break;
+            case XAException.XA_HEURRB:
+              if (!committed.isEmpty() || heurCode == XAException.XA_HEURCOM) {
+                heurCode = XAException.XA_HEURMIX;
+              } else if (heurCode == 0) {
+                heurCode = XAException.XA_HEURRB;
+              } // else it's a HEURHAZ or a HEURRB and stays that way.
+              break;
+            case XAException.XA_HEURMIX:
+              // It can't get worse than, we know we have a mixed result.
+              heurCode = XAException.XA_HEURMIX;
+              break;
+            default:
+              // The codes above are the only codes permitted from a rollback() so
+              // anything else indicates a serious error in the resource-manager.
+              throw new XAException(XAException.XAER_RMERR);
+          }
+        }
+
+        throw new XAException(heurCode);
+      }
+    } finally {
+      cleanupTransaction();
+    }
+  }
+
+
+  Xid getXid() {
+    return xid;
+  }
+
+  private void cleanupTransaction() throws XAException {
+    report("cleanupTransaction");
+    try {
+      factory.transactionComplete(this);
+    } catch (MulgaraTransactionException em) {
+      try {
+        logger.error("Failed to cleanup transaction", em);
+        abortTransaction("Failure in cleanup", em);
+        throw new XAException(XAException.XAER_RMERR);
+      } catch (MulgaraTransactionException em2) {
+        logger.error("Failed to abort transaction on cleanup failure", em2);
+        throw new XAException(XAException.XAER_RMFAIL);
+      }
+    }
+  }
+
+  private void report(String desc) {
+    if (logger.isInfoEnabled()) {
+      logger.info(desc + ": " + System.identityHashCode(this));
+    }
+  }
+}

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransactionFactory.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransactionFactory.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransactionFactory.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraExternalTransactionFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,243 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com) under contract to 
+ * Topaz Foundation. Portions created under this contract are
+ * Copyright (c) 2007 Topaz Foundation
+ * All Rights Reserved.
+ */
+
+package org.mulgara.resolver;
+
+// Java2 packages
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.query.QueryException;
+import org.mulgara.transaction.TransactionManagerFactory;
+import org.mulgara.util.Assoc1toNMap;
+
+/**
+ * Manages external transactions.
+ *
+ * @created 2007-11-06
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ *
+ * @copyright &copy;2007 <a href="http://www.topazproject.org/">Topaz Foundation</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public class MulgaraExternalTransactionFactory extends MulgaraTransactionFactory {
+  private Map<DatabaseSession, MulgaraExternalTransaction> associatedTransaction;
+  private Assoc1toNMap<DatabaseSession, MulgaraExternalTransaction> sessionXAMap;
+
+  private Map<DatabaseSession, MulgaraXAResourceContext> xaResources;
+
+  public MulgaraExternalTransactionFactory(MulgaraTransactionManager manager) {
+    super(manager);
+
+    this.associatedTransaction = new HashMap<DatabaseSession, MulgaraExternalTransaction>();
+    this.sessionXAMap = new Assoc1toNMap<DatabaseSession, MulgaraExternalTransaction>();
+    this.xaResources = new HashMap<DatabaseSession, MulgaraXAResourceContext>();
+  }
+
+  public MulgaraTransaction getTransaction(final DatabaseSession session, boolean write)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      MulgaraExternalTransaction xa = associatedTransaction.get(session);
+      if (xa == null) {
+        throw new MulgaraTransactionException("No externally mediated transaction associated with session");
+      } else if (write && xa != writeTransaction) {
+        throw new MulgaraTransactionException("RO-transaction associated with session when requesting write operation");
+      }
+
+      return xa;
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  protected MulgaraExternalTransaction createTransaction(final DatabaseSession session, Xid xid, boolean write)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (associatedTransaction.get(session) != null) {
+        throw new MulgaraTransactionException(
+            "Attempt to initiate transaction with existing transaction active with session");
+      }
+      if (write && manager.isHoldingWriteLock(session)) {
+        throw new MulgaraTransactionException("Attempt to initiate two write transactions from the same session");
+      }
+
+      if (write) {
+          runWithoutMutex(new TransactionOperation() {
+            public void execute() throws MulgaraTransactionException {
+              manager.obtainWriteLock(session);
+            }
+          });
+        try {
+          MulgaraExternalTransaction xa = new MulgaraExternalTransaction(this, xid, session.newOperationContext(true));
+          writeTransaction = xa;
+          associatedTransaction.put(session, xa);
+          sessionXAMap.put(session, xa);
+
+          return xa;
+        } catch (Throwable th) {
+          manager.releaseWriteLock(session);
+          throw new MulgaraTransactionException("Error initiating write transaction", th);
+        }
+      } else {
+        try {
+          MulgaraExternalTransaction xa = new MulgaraExternalTransaction(this, xid, session.newOperationContext(false));
+          associatedTransaction.put(session, xa);
+          sessionXAMap.put(session, xa);
+
+          return xa;
+        } catch (QueryException eq) {
+          throw new MulgaraTransactionException("Error obtaining new read-only operation-context", eq);
+        }
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public Set<MulgaraExternalTransaction> getTransactionsForSession(DatabaseSession session) {
+    acquireMutex();
+    try {
+      Set<MulgaraExternalTransaction> xas = sessionXAMap.getN(session);
+      return xas != null ? xas : Collections.<MulgaraExternalTransaction>emptySet();
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public XAResource getXAResource(DatabaseSession session, boolean writing) {
+    acquireMutex();
+    try {
+      MulgaraXAResourceContext xarc = xaResources.get(session);
+      if (xarc == null) {
+        xarc = new MulgaraXAResourceContext(this, session);
+        xaResources.put(session, xarc);
+      }
+
+      return xarc.getResource(writing);
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void closingSession(DatabaseSession session) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      try {
+        super.closingSession(session);
+      } finally {
+        xaResources.remove(session);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void transactionComplete(MulgaraExternalTransaction xa)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (xa == null) {
+        throw new IllegalArgumentException("Null transaction indicated completion");
+      }
+      DatabaseSession session = sessionXAMap.get1(xa);
+      if (xa == writeTransaction) {
+        manager.releaseWriteLock(session);
+        writeTransaction = null;
+      }
+      sessionXAMap.removeN(xa);
+      if (associatedTransaction.get(session) == xa) {
+        associatedTransaction.remove(session);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public boolean hasAssociatedTransaction(DatabaseSession session) {
+    acquireMutex();
+    try {
+      return associatedTransaction.get(session) != null;
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public boolean associateTransaction(DatabaseSession session, MulgaraExternalTransaction xa) {
+    acquireMutex();
+    try {
+      if (associatedTransaction.get(session) != null) {
+        return false;
+      } else {
+        associatedTransaction.put(session, xa);
+        return true;
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public MulgaraExternalTransaction getAssociatedTransaction(DatabaseSession session) {
+    acquireMutex();
+    try {
+      return associatedTransaction.get(session);
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void disassociateTransaction(DatabaseSession session, MulgaraExternalTransaction xa) 
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (associatedTransaction.get(session) == xa) {
+        associatedTransaction.remove(session);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  void abortWriteTransaction() throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (writeTransaction != null) {
+        writeTransaction.abortTransaction("Explicit abort requested by write-lock manager", new Throwable());
+        writeTransaction = null;
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+}

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransaction.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransaction.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransaction.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransaction.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,741 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com). Portions created
+ * by Netymon Pty Ltd are Copyright (c) 2006 Netymon Pty Ltd.
+ * All Rights Reserved.
+ *
+ * Work deriving from MulgaraTransaction Copyright (c) 2007 Topaz Foundation
+ * under contract by Andrae Muys (mailto:andrae at netymon.com).
+ */
+package org.mulgara.resolver;
+
+// Java 2 enterprise packages
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAResource;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.resolver.spi.DatabaseMetadata;
+import org.mulgara.resolver.spi.EnlistableResource;
+import org.mulgara.resolver.spi.ResolverSessionFactory;
+
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.QueryException;
+
+/**
+ * Responsible for the javax.transaction.Transaction object.
+ * Responsibilities
+ * Ensuring every begin or resume is followed by either a suspend or an end.
+ * Ensuring every suspend or end is preceeded by either a begin or a resume.
+ * In conjunction with TransactionalAnswer ensuring that
+ * all calls to operations on SubqueryAnswer are preceeded by a successful resume.
+ * all calls to operations on SubqueryAnswer conclude with a suspend as the last call prior to returning to the user.
+ * Collaborates with DatabaseTransactionManager to determine when to end the transaction.
+ *
+ * @created 2006-10-06
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <a href="mailto:mail at netymon.com">Netymon Pty Ltd</a>
+ *
+ * @copyright &copy;2006 <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
+ *
+ * @licence Open Software License v3.0
+ */
+public class MulgaraInternalTransaction implements MulgaraTransaction {
+  /**
+   * This is the state machine switch matching these states.
+      switch (state) {
+        case CONSTRUCTEDREF:
+        case CONSTRUCTEDUNREF:
+        case ACTUNREF:
+        case ACTREF:
+        case DEACTREF:
+        case FINISHED:
+        case FAILED:
+      }
+   */
+  private enum State { CONSTRUCTEDREF, CONSTRUCTEDUNREF, ACTUNREF, ACTREF, DEACTREF, FINISHED, FAILED };
+
+  /** Logger.  */
+  private static final Logger logger =
+    Logger.getLogger(MulgaraInternalTransaction.class.getName());
+
+  private MulgaraInternalTransactionFactory factory;
+  private DatabaseOperationContext context;
+  private Set<EnlistableResource> enlisted;
+
+  private Transaction transaction;
+  private Thread currentThread;
+
+  private ReentrantLock activationMutex;
+
+  private State state;
+  private int inuse;
+  private int using;
+
+  private Throwable rollbackCause;
+
+  public MulgaraInternalTransaction(MulgaraInternalTransactionFactory factory, DatabaseOperationContext context)
+      throws IllegalArgumentException {
+    report("Creating Transaction");
+
+    try {
+      if (factory == null) {
+        throw new IllegalArgumentException("Manager null in MulgaraTransaction");
+      } else if (context == null) {
+        throw new IllegalArgumentException("OperationContext null in MulgaraTransaction");
+      }
+      this.factory = factory;
+      this.context = context;
+      this.enlisted = new HashSet<EnlistableResource>();
+      this.activationMutex = new ReentrantLock();
+      this.currentThread = null;
+
+      inuse = 0;
+      using = 0;
+      state = State.CONSTRUCTEDUNREF;
+      rollbackCause = null;
+    } finally {
+      report("Finished Creating Transaction");
+    }
+  }
+
+
+  void activate() throws MulgaraTransactionException {
+//    report("Activating Transaction");
+    try {
+      synchronized (this) {
+        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+      
+      acquireActivationMutex();
+      try {
+        switch (state) {
+          case CONSTRUCTEDUNREF:
+            startTransaction();
+            inuse = 1;
+            state = State.ACTUNREF;
+            try {
+              context.initiate(this);
+            } catch (Throwable th) {
+              throw implicitRollback(th);
+            }
+            break;
+          case CONSTRUCTEDREF:
+            startTransaction();
+            inuse = 1;
+            using = 1;
+            state = State.ACTREF;
+            try {
+              context.initiate(this);
+            } catch (Throwable th) {
+              throw implicitRollback(th);
+            }
+            break;
+          case DEACTREF:
+            resumeTransaction();
+            inuse = 1;
+            state = State.ACTREF;
+            break;
+          case ACTREF:
+          case ACTUNREF:
+            inuse++;
+            break;
+          case FINISHED:
+            throw new MulgaraTransactionException("Attempt to activate terminated transaction");
+          case FAILED:
+            throw new MulgaraTransactionException("Attempt to activate failed transaction", rollbackCause);
+        }
+      } finally {
+        releaseActivationMutex();
+      }
+
+      try {
+        checkActivated();
+      } catch (MulgaraTransactionException em) {
+        throw abortTransaction("Activate failed post-condition check", em);
+      }
+    } catch (MulgaraTransactionException em) {
+      throw em;
+    } catch (Throwable th) {
+      throw abortTransaction("Error activating transaction", th);
+    } finally {
+//      report("Leaving Activate transaction");
+    }
+  }
+
+
+  private void deactivate() throws MulgaraTransactionException {
+//    report("Deactivating transaction");
+
+    try {
+      synchronized (this) {
+        if (currentThread == null) {
+          throw new MulgaraTransactionException("Transaction not associated with thread");
+        } else if (!currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+      
+      acquireActivationMutex();
+      try {
+        switch (state) {
+          case ACTUNREF:
+            if (inuse == 1) {
+              commitTransaction();
+            }
+            inuse--;
+            break;
+          case ACTREF:
+            if (inuse == 1) {
+              suspendTransaction();
+            }
+            inuse--;
+            break;
+          case CONSTRUCTEDREF:
+            throw new MulgaraTransactionException("Attempt to deactivate uninitiated refed transaction");
+          case CONSTRUCTEDUNREF:
+            throw new MulgaraTransactionException("Attempt to deactivate uninitiated transaction");
+          case DEACTREF:
+            throw new IllegalStateException("Attempt to deactivate unactivated transaction");
+          case FINISHED:
+            if (inuse < 0) {
+              errorReport("Activation count failure - too many deacts - in finished transaction", null);
+            } else {
+              inuse--;
+            }
+            break;
+          case FAILED:
+            // Nothing to do here.
+            break;
+        }
+      } finally {
+        releaseActivationMutex();
+      }
+    } catch (MulgaraTransactionException em) {
+      throw em;
+    } catch (Throwable th) {
+      throw abortTransaction("Error deactivating transaction", th);
+    } finally {
+//      report("Leaving Deactivate Transaction");
+    }
+  }
+
+  // Note: The transaction is often not activated when these are called.
+  //       This occurs when setting autocommit, as this creates and
+  //       references a transaction object that won't be started/activated
+  //       until it is first used.
+  public void reference() throws MulgaraTransactionException {
+    try {
+      report("Referencing Transaction");
+
+      synchronized (this) {
+        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+
+      switch (state) {
+        case CONSTRUCTEDUNREF:
+          state = State.CONSTRUCTEDREF;
+          break;
+        case ACTREF:
+        case ACTUNREF:
+          using++;
+          state = State.ACTREF;
+          break;
+        case DEACTREF:
+          using++;
+          break;
+        case CONSTRUCTEDREF:
+          throw new MulgaraTransactionException("Attempt to reference uninitated transaction twice");
+        case FINISHED:
+          throw new MulgaraTransactionException("Attempt to reference terminated transaction");
+        case FAILED:
+          throw new MulgaraTransactionException("Attempt to reference failed transaction", rollbackCause);
+      }
+    } catch (MulgaraTransactionException em) {
+      throw em;
+    } catch (Throwable th) {
+      report("Error referencing transaction");
+      throw implicitRollback(th);
+    } finally {
+      report("Leaving Reference Transaction");
+    }
+  }
+
+  public void dereference() throws MulgaraTransactionException {
+    report("Dereferencing Transaction");
+    try {
+      synchronized (this) {
+        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+
+      switch (state) {
+        case ACTREF:
+          if (using == 1) {
+            state = State.ACTUNREF;
+          }
+          using--;
+          break;
+        case CONSTRUCTEDREF:
+          state = State.CONSTRUCTEDUNREF;
+          break;
+        case FINISHED:
+        case FAILED:
+          if (using < 1) {
+            errorReport("Reference count failure - too many derefs - in finished transaction", null);
+          } else {
+            using--;
+          }
+          break;
+        case ACTUNREF:
+          throw new IllegalStateException("Attempt to dereference unreferenced transaction");
+        case CONSTRUCTEDUNREF:
+          throw new MulgaraTransactionException("Attempt to dereference uninitated transaction");
+        case DEACTREF:
+          throw new IllegalStateException("Attempt to dereference deactivated transaction");
+      }
+    } catch (MulgaraTransactionException em) {
+      throw em;
+    } catch (Throwable th) {
+      throw implicitRollback(th);
+    } finally {
+      report("Dereferenced Transaction");
+    }
+  }
+
+  private void startTransaction() throws MulgaraTransactionException {
+    report("Initiating transaction");
+    try {
+      transaction = factory.transactionStart(this);
+      synchronized (this) {
+        currentThread = Thread.currentThread();
+      }
+    } catch (Throwable th) {
+      throw abortTransaction("Failed to start transaction", th);
+    }
+  }
+
+  private void resumeTransaction() throws MulgaraTransactionException {
+//    report("Resuming transaction");
+    try {
+      factory.transactionResumed(this, transaction);
+      synchronized (this) {
+        currentThread = Thread.currentThread();
+      }
+    } catch (Throwable th) {
+      abortTransaction("Failed to resume transaction", th);
+    }
+  }
+
+  private void suspendTransaction() throws MulgaraTransactionException {
+//    report("Suspending Transaction");
+    try {
+      if (using < 1) {
+        throw implicitRollback(
+            new MulgaraTransactionException("Attempt to suspend unreferenced transaction"));
+      }
+      transaction = factory.transactionSuspended(this);
+      synchronized (this) {
+        currentThread = null;
+      }
+      state = State.DEACTREF;
+    } catch (Throwable th) {
+      throw implicitRollback(th);
+    } finally {
+//      report("Finished suspending transaction");
+    }
+  }
+
+  public void commitTransaction() throws MulgaraTransactionException {
+    report("Committing Transaction");
+    try {
+      transaction.commit();
+    } catch (Throwable th) {
+      throw implicitRollback(th);
+    }
+    try {
+      try {
+        transaction = null;
+      } finally { try {
+        state = State.FINISHED;
+      } finally { try {
+        context.clear();
+      } finally { try {
+        enlisted.clear();
+      } finally { try {
+        factory.transactionComplete(this);
+      } finally { try {
+        factory = null;
+      } finally {
+        report("Committed transaction");
+      } } } } } }
+    } catch (Throwable th) {
+      errorReport("Error cleaning up transaction post-commit", th);
+      throw new MulgaraTransactionException("Error cleaning up transaction post-commit", th);
+    }
+  }
+
+  public void heuristicRollback(String cause) throws MulgaraTransactionException {
+    implicitRollback(new MulgaraTransactionException(cause));
+  }
+
+  /**
+   * Rollback the transaction.
+   * We don't throw an exception here when transaction fails - this is expected,
+   * after all we requested it.
+   */
+  public void explicitRollback() throws MulgaraTransactionException {
+    synchronized (this) {
+      if (currentThread == null) {
+        throw new MulgaraTransactionException("Transaction failed activation check");
+      } else if (!currentThread.equals(Thread.currentThread())) {
+        throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+      }
+    }
+
+    try {
+      switch (state) {
+        case ACTUNREF:
+        case ACTREF:
+          transaction.rollback();
+          context.clear();
+          enlisted.clear();
+          factory.transactionComplete(this);
+          state = State.FINISHED;
+          break;
+        case DEACTREF:
+          throw new IllegalStateException("Attempt to rollback unactivated transaction");
+        case CONSTRUCTEDREF:
+          throw new MulgaraTransactionException("Attempt to rollback uninitiated ref'd transaction");
+        case CONSTRUCTEDUNREF:
+          throw new MulgaraTransactionException("Attempt to rollback uninitiated unref'd transaction");
+        case FINISHED:
+          throw new MulgaraTransactionException("Attempt to rollback finished transaction");
+        case FAILED:
+          throw new MulgaraTransactionException("Attempt to rollback failed transaction");
+      }
+    } catch (MulgaraTransactionException em) {
+      throw em;
+    } catch (Throwable th) {
+      throw implicitRollback(th);
+    }
+  }
+
+  /**
+   * This will endevour to terminate the transaction via a rollback - if this
+   * fails it will abort the transaction.
+   * If the rollback succeeds then this method will return a suitable
+   * MulgaraTransactionException to be thrown by the caller.
+   * If the rollback fails then this method will throw the resulting exception
+   * from abortTransaction().
+   * Post-condition: The transaction is terminated and cleaned up.
+   */
+  MulgaraTransactionException implicitRollback(Throwable cause) throws MulgaraTransactionException {
+    try {
+      report("Implicit Rollback triggered");
+
+      synchronized (this) {
+        if (currentThread == null) {
+          throw new MulgaraTransactionException("Transaction not associated with thread");
+        } else if (!currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+
+      if (rollbackCause != null) {
+        errorReport("Cascading error, transaction already rolled back", cause);
+        errorReport("Cascade error, expected initial cause", rollbackCause);
+
+        return new MulgaraTransactionException("Transaction already in rollback", cause);
+      }
+
+      switch (state) {
+        case ACTUNREF:
+        case ACTREF:
+            rollbackCause = cause;
+            transaction.rollback();
+            transaction = null;
+            context.clear();
+            enlisted.clear();
+            state = State.FAILED;
+            factory.transactionComplete(this);
+            factory = null;
+            return new MulgaraTransactionException("Transaction rollback triggered", cause);
+        case DEACTREF:
+          throw new IllegalStateException("Attempt to rollback deactivated transaction");
+        case CONSTRUCTEDREF:
+          throw new MulgaraTransactionException("Attempt to rollback uninitiated ref'd transaction");
+        case CONSTRUCTEDUNREF:
+          throw new MulgaraTransactionException("Attempt to rollback uninitiated unref'd transaction");
+        case FINISHED:
+          throw new MulgaraTransactionException("Attempt to rollback finished transaction");
+        case FAILED:
+          throw new MulgaraTransactionException("Attempt to rollback failed transaction");
+        default:
+          throw new MulgaraTransactionException("Unknown state");
+      }
+    } catch (Throwable th) {
+      try {
+        errorReport("Attempt to rollback failed; initiating cause: ", cause);
+      } finally {
+        throw abortTransaction("Failed to rollback normally - see log for inititing cause", th);
+      }
+    } finally {
+      report("Leaving implicitRollback");
+    }
+  }
+
+  /**
+   * Forces the transaction to be abandoned, including bypassing JTA to directly
+   * rollback/abort the underlying store-phases if required.
+   * Heavilly nested try{}finally{} should guarentee that even JVM errors should
+   * not prevent this function from cleaning up anything that can be cleaned up.
+   * We have to delegate to the OperationContext the abort() on the resolvers as
+   * only it has full knowledge of which resolvers are associated with this
+   * transaction.
+   */
+  public MulgaraTransactionException abortTransaction(String errorMessage, Throwable cause)
+      throws MulgaraTransactionException {
+    // We need to notify the factory here - this is serious, we
+    // need to rollback this transaction, but if we have reached here
+    // we have failed to obtain a valid transaction to rollback!
+    try {
+      try {
+        errorReport(errorMessage + " - Aborting", cause);
+      } finally { try {
+        if (transaction != null) {
+          transaction.rollback();
+        }
+      } finally { try {
+        factory.transactionAborted(this);
+      } finally { try {
+        abortEnlistedResources();
+      } finally { try {
+        context.clear();
+      } finally { try {
+        enlisted.clear();
+      } finally { try {
+        transaction = null;
+      } finally { try {
+        factory = null;
+      } finally {
+        state = State.FAILED;
+      } } } } } } } }
+      return new MulgaraTransactionException(errorMessage + " - Aborting", cause);
+    } catch (Throwable th) {
+      throw new MulgaraTransactionException(errorMessage + " - Failed to abort cleanly", th);
+    } finally {
+      report("Leaving abortTransaction");
+    }
+  }
+
+  /**
+   * Used to bypass JTA and explicitly abort resources behind the scenes.
+   */
+  private void abortEnlistedResources() {
+    for (EnlistableResource e : enlisted) {
+      try {
+        e.abort();
+      } catch (Throwable th) {
+        try {
+          errorReport("Error aborting enlistable resource", th);
+        } catch (Throwable ignore) { }
+      }
+    }
+  }
+
+  public void execute(Operation operation, DatabaseMetadata metadata) throws MulgaraTransactionException {
+    report("Executing Operation");
+    try {
+      activate();
+      try {
+        operation.execute(context,
+                          context.getSystemResolver(),
+                          metadata);
+      } catch (Throwable th) {
+        throw implicitRollback(th);
+      } finally {
+        deactivate();
+      }
+    } finally {
+      report("Executed Operation");
+    }
+  }
+
+  public AnswerOperationResult execute(AnswerOperation ao) throws TuplesException {
+    debugReport("Executing AnswerOperation");
+    try {
+      activate();
+      try {
+        ao.execute();
+        return ao.getResult();
+      } catch (Throwable th) {
+        throw implicitRollback(th);
+      } finally {
+        deactivate();
+      }
+    } catch (MulgaraTransactionException em) {
+      throw new TuplesException("Transaction error", em);
+    } finally {
+      debugReport("Executed AnswerOperation");
+    }
+  }
+
+
+  public void execute(TransactionOperation to) throws MulgaraTransactionException {
+    report("Executing TransactionOperation");
+    try {
+      activate();
+      try {
+        to.execute();
+      } catch (Throwable th) {
+        throw implicitRollback(th);
+      } finally {
+        deactivate();
+      }
+    } finally {
+      report("Executed TransactionOperation");
+    }
+  }
+
+  public void enlist(EnlistableResource enlistable) throws MulgaraTransactionException {
+    try {
+      synchronized (this) {
+        if (currentThread == null) {
+          throw new MulgaraTransactionException("Transaction not associated with thread");
+        } else if (!currentThread.equals(Thread.currentThread())) {
+          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+        }
+      }
+
+      if (enlisted.contains(enlistable)) {
+        return;
+      }
+
+      switch (state) {
+        case ACTUNREF:
+        case ACTREF:
+          transaction.enlistResource(enlistable.getXAResource());
+          enlisted.add(enlistable);
+          break;
+        case CONSTRUCTEDREF:
+          throw new MulgaraTransactionException("Attempt to enlist resource in uninitated ref'd transaction");
+        case CONSTRUCTEDUNREF:
+          throw new MulgaraTransactionException("Attempt to enlist resource in uninitated unref'd transaction");
+        case DEACTREF:
+          throw new MulgaraTransactionException("Attempt to enlist resource in unactivated transaction");
+        case FINISHED:
+          throw new MulgaraTransactionException("Attempt to enlist resource in finished transaction");
+        case FAILED:
+          throw new MulgaraTransactionException("Attempt to enlist resource in failed transaction");
+      }
+    } catch (Throwable th) {
+      throw implicitRollback(th);
+    }
+  }
+
+  //
+  // Used internally
+  //
+
+  private void checkActivated() throws MulgaraTransactionException {
+    synchronized (this) {
+      if (currentThread == null) {
+        throw new MulgaraTransactionException("Transaction not associated with thread");
+      } else if (!currentThread.equals(Thread.currentThread())) {
+        throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
+      }
+    }
+
+    switch (state) {
+      case ACTUNREF:
+      case ACTREF:
+        if (inuse < 0 || using < 0) {
+          throw new MulgaraTransactionException("Reference Failure, using: " + using + ", inuse: " + inuse);
+        }
+        return;
+      case CONSTRUCTEDREF:
+        throw new MulgaraTransactionException("Transaction (ref) uninitiated");
+      case CONSTRUCTEDUNREF:
+        throw new MulgaraTransactionException("Transaction (unref) uninitiated");
+      case DEACTREF:
+        throw new MulgaraTransactionException("Transaction deactivated");
+      case FINISHED:
+        throw new MulgaraTransactionException("Transaction is terminated");
+      case FAILED:
+        throw new MulgaraTransactionException("Transaction is failed", rollbackCause);
+    }
+  }
+
+  private void acquireActivationMutex() {
+    activationMutex.lock();
+  }
+
+  private void releaseActivationMutex() {
+    activationMutex.unlock();
+  }
+
+  protected void finalize() {
+    report("GC-finalize");
+    if (state != State.FINISHED && state != State.FAILED) {
+      errorReport("Finalizing incomplete transaction - aborting...", null);
+      try {
+        abortTransaction("Transaction finalized while still valid", new Throwable());
+      } catch (Throwable th) {
+        errorReport("Attempt to abort transaction from finalize failed", th);
+      }
+    }
+
+    if (state != State.FAILED && (inuse != 0 || using != 0)) {
+      errorReport("Reference counting error in transaction", null);
+    }
+
+    if (factory != null || transaction != null) {
+      errorReport("Transaction not terminated properly", null);
+    }
+  }
+
+  private void report(String desc) {
+    if (logger.isInfoEnabled()) {
+      logger.info(desc + ": " + System.identityHashCode(this) + ", state=" + state +
+          ", inuse=" + inuse + ", using=" + using);
+    }
+  }
+
+  private void debugReport(String desc) {
+    if (logger.isDebugEnabled()) {
+      logger.debug(desc + ": " + System.identityHashCode(this) + ", state=" + state +
+          ", inuse=" + inuse + ", using=" + using);
+    }
+  }
+
+  private void errorReport(String desc, Throwable cause) {
+    logger.error(desc + ": " + System.identityHashCode(this) + ", state=" + state +
+        ", inuse=" + inuse + ", using=" + using, cause != null ? cause : new Throwable());
+  }
+}

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransactionFactory.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransactionFactory.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransactionFactory.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraInternalTransactionFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,421 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com). Portions created
+ * by Netymon Pty Ltd are Copyright (c) 2006 Netymon Pty Ltd.
+ * All Rights Reserved.
+ *
+ * Work deriving from MulgaraTransactionManager Copyright (c) 2007 Topaz
+ * Foundation under contract by Andrae Muys (mailto:andrae at netymon.com).
+ */
+
+package org.mulgara.resolver;
+
+// Java2 packages
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.transaction.TransactionManagerFactory;
+import org.mulgara.util.Assoc1toNMap;
+
+/**
+ * Implements the internal transaction controls offered by Session.
+ *
+ * @created 2006-10-06
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ *
+ * @copyright &copy;2006 <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public class MulgaraInternalTransactionFactory extends MulgaraTransactionFactory {
+  /** Logger.  */
+  private static final Logger logger =
+    Logger.getLogger(MulgaraInternalTransactionFactory.class.getName());
+
+  private boolean autoCommit;
+
+  /** Set of sessions whose transactions have been rolledback.*/
+  private Set<DatabaseSession> failedSessions;
+
+  /** Map of threads to active transactions. */
+  private Map<Thread, MulgaraTransaction> activeTransactions;
+
+  private Assoc1toNMap<DatabaseSession, MulgaraTransaction> sessionXAMap;
+
+  private final TransactionManager transactionManager;
+
+  public MulgaraInternalTransactionFactory(MulgaraTransactionManager manager, TransactionManagerFactory transactionManagerFactory) {
+    super(manager);
+    this.autoCommit = true;
+
+    this.failedSessions = new HashSet<DatabaseSession>();
+    this.activeTransactions = new HashMap<Thread, MulgaraTransaction>();
+    this.sessionXAMap = new Assoc1toNMap<DatabaseSession, MulgaraTransaction>();
+
+    this.transactionManager = transactionManagerFactory.newTransactionManager();
+  }
+
+  public MulgaraTransaction getTransaction(final DatabaseSession session, boolean write)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (manager.isHoldingWriteLock(session)) {
+        return writeTransaction;
+      }
+
+      try {
+        MulgaraInternalTransaction transaction;
+        if (write) {
+          runWithoutMutex(new TransactionOperation() {
+            public void execute() throws MulgaraTransactionException {
+              manager.obtainWriteLock(session);
+            }
+          });
+          try {
+            assert writeTransaction == null;
+            writeTransaction = transaction = 
+                new MulgaraInternalTransaction(this, session.newOperationContext(true));
+          } catch (Throwable th) {
+            manager.releaseWriteLock(session);
+            throw new MulgaraTransactionException("Error creating write transaction", th);
+          }
+        } else {
+          transaction = new MulgaraInternalTransaction(this, session.newOperationContext(false));
+        }
+
+        sessionXAMap.put(session, transaction);
+
+        return transaction;
+      } catch (MulgaraTransactionException em) {
+        throw em;
+      } catch (Exception e) {
+        throw new MulgaraTransactionException("Error creating transaction", e);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public Set<MulgaraTransaction> getTransactionsForSession(DatabaseSession session) {
+    acquireMutex();
+    try {
+      Set <MulgaraTransaction> xas = sessionXAMap.getN(session);
+      return xas == null ? Collections.<MulgaraTransaction>emptySet() : xas;
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public MulgaraTransaction newMulgaraTransaction(DatabaseOperationContext context)
+      throws MulgaraTransactionException {
+    return new MulgaraInternalTransaction(this, context);
+  }
+
+
+  public void commit(DatabaseSession session) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      manager.reserveWriteLock(session);
+      try {
+        if (failedSessions.contains(session)) {
+          throw new MulgaraTransactionException("Attempting to commit failed exception");
+        } else if (!manager.isHoldingWriteLock(session)) {
+          throw new MulgaraTransactionException(
+              "Attempting to commit while not the current writing transaction");
+        }
+
+        setAutoCommit(session, true);
+        setAutoCommit(session, false);
+      } finally {
+        manager.releaseReserve(session);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+
+  /**
+   * This is an explicit, user-specified rollback.
+   * 
+   * This needs to be distinguished from an implicit rollback triggered by failure.
+   */
+  public void rollback(DatabaseSession session) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      manager.reserveWriteLock(session);
+      try {
+        if (manager.isHoldingWriteLock(session)) {
+          try {
+            writeTransaction.execute(new TransactionOperation() {
+                public void execute() throws MulgaraTransactionException {
+                  writeTransaction.heuristicRollback("Explicit Rollback");
+                }
+            });
+            // FIXME: Should be checking status here, not writelock.
+            if (manager.isHoldingWriteLock(session)) {
+              // transaction referenced by something - need to explicitly end it.
+              writeTransaction.abortTransaction("Rollback failed",
+                  new MulgaraTransactionException("Rollback failed to terminate write transaction"));
+            }
+          } finally {
+            failedSessions.add(session);
+            setAutoCommit(session, false);
+          }
+        } else if (failedSessions.contains(session)) {
+          failedSessions.remove(session);
+          setAutoCommit(session, false);
+        } else {
+          throw new MulgaraTransactionException(
+              "Attempt to rollback while not in the current writing transaction");
+        }
+      } finally {
+        manager.releaseReserve(session);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void setAutoCommit(DatabaseSession session, boolean autoCommit)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (manager.isHoldingWriteLock(session) && failedSessions.contains(session)) {
+        writeTransaction.abortTransaction("Session failed and still holding writeLock",
+            new MulgaraTransactionException("Failed Session in setAutoCommit"));
+      }
+
+      if (manager.isHoldingWriteLock(session) || failedSessions.contains(session)) {
+        if (autoCommit) {
+          // AutoCommit off -> on === branch on current state of transaction.
+          if (manager.isHoldingWriteLock(session)) {
+            // Within active transaction - commit and finalise.
+            try {
+              runWithoutMutex(new TransactionOperation() {
+                public void execute() throws MulgaraTransactionException {
+                  writeTransaction.execute(new TransactionOperation() {
+                    public void execute() throws MulgaraTransactionException {
+                      writeTransaction.dereference();
+                      ((MulgaraInternalTransaction)writeTransaction).commitTransaction();
+                    }
+                  });
+                }
+              });
+            } finally {
+              // This should have been cleaned up by the commit above, but if it
+              // hasn't then if we don't release here we could deadlock the
+              // transaction manager
+              if (manager.isHoldingWriteLock(session)) {
+                manager.releaseWriteLock(session);
+              }
+              this.autoCommit = true;
+            }
+          } else if (failedSessions.contains(session)) {
+            // Within failed transaction - cleanup.
+            failedSessions.remove(session);
+          }
+        } else {
+          if (!manager.isHoldingWriteLock(session)) {
+            if (failedSessions.contains(session)) {
+              failedSessions.remove(session);
+              setAutoCommit(session, false);
+            } else {
+              throw new IllegalStateException("Can't reach here");
+            }
+          } else {
+            // AutoCommit off -> off === no-op. Log info.
+            if (logger.isInfoEnabled()) {
+              logger.info("Attempt to set autocommit false twice", new Throwable());
+            }
+          }
+        }
+      } else {
+        if (autoCommit) {
+          // AutoCommit on -> on === no-op.  Log info.
+          logger.info("Attempting to set autocommit true without setting it false");
+        } else {
+          // AutoCommit on -> off == Start new transaction.
+          getTransaction(session, true); // Set's writeTransaction.
+          writeTransaction.reference();
+          this.autoCommit = false;
+        }
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  //
+  // Transaction livecycle callbacks.
+  //
+
+  public Transaction transactionStart(MulgaraTransaction transaction) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      try {
+        logger.info("Beginning Transaction");
+        if (activeTransactions.get(Thread.currentThread()) != null) {
+          throw new MulgaraTransactionException(
+              "Attempt to start transaction in thread with exiting active transaction.");
+        } else if (activeTransactions.containsValue(transaction)) {
+          throw new MulgaraTransactionException("Attempt to start transaction twice");
+        }
+
+        transactionManager.begin();
+        Transaction jtaTrans = transactionManager.getTransaction();
+
+        activeTransactions.put(Thread.currentThread(), transaction);
+
+        return jtaTrans;
+      } catch (Exception e) {
+        throw new MulgaraTransactionException("Transaction Begin Failed", e);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void transactionResumed(MulgaraTransaction transaction, Transaction jtaXA) 
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (activeTransactions.get(Thread.currentThread()) != null) {
+        throw new MulgaraTransactionException(
+            "Attempt to resume transaction in already activated thread");
+      } else if (activeTransactions.containsValue(transaction)) {
+        throw new MulgaraTransactionException("Attempt to resume active transaction");
+      }
+      
+      try {
+        transactionManager.resume(jtaXA);
+        activeTransactions.put(Thread.currentThread(), transaction);
+      } catch (Exception e) {
+        throw new MulgaraTransactionException("Resume Failed", e);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public Transaction transactionSuspended(MulgaraTransaction transaction)
+      throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      try {
+        if (transaction != activeTransactions.get(Thread.currentThread())) {
+          throw new MulgaraTransactionException(
+              "Attempt to suspend transaction from outside thread");
+        }
+
+        if (autoCommit && transaction == writeTransaction) {
+          logger.error("Attempt to suspend write transaction without setting AutoCommit Off");
+          throw new MulgaraTransactionException(
+              "Attempt to suspend write transaction without setting AutoCommit Off");
+        }
+
+        Transaction xa = transactionManager.suspend();
+        activeTransactions.remove(Thread.currentThread());
+
+        return xa;
+      } catch (Throwable th) {
+        logger.error("Attempt to suspend failed", th);
+        try {
+          transactionManager.setRollbackOnly();
+        } catch (Throwable t) {
+          logger.error("Attempt to setRollbackOnly() failed", t);
+        }
+        throw new MulgaraTransactionException("Suspend failed", th);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void transactionComplete(MulgaraTransaction transaction) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      logger.debug("Transaction Complete");
+      DatabaseSession session = sessionXAMap.get1(transaction);
+      if (session == null) {
+        throw new MulgaraTransactionException("No associated session found for transaction");
+      }
+      if (manager.isHoldingWriteLock(session)) {
+        manager.releaseWriteLock(session);
+        writeTransaction = null;
+      }
+
+      sessionXAMap.removeN(transaction);
+      activeTransactions.remove(Thread.currentThread());
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void transactionAborted(MulgaraTransaction transaction) {
+    acquireMutex();
+    try {
+      try {
+        // Make sure this cleans up the transaction metadata - this transaction is DEAD!
+        if (transaction == writeTransaction) {
+          failedSessions.add(sessionXAMap.get1(transaction));
+        }
+        transactionComplete(transaction);
+      } catch (Throwable th) {
+        // FIXME: This should probably abort the entire server after logging the error!
+        logger.error("Error managing transaction abort", th);
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  public void setTransactionTimeout(int transactionTimeout) {
+    try {
+      transactionManager.setTransactionTimeout(transactionTimeout);
+    } catch (SystemException es) {
+      logger.warn("Unable to set transaction timeout: " + transactionTimeout, es);
+    }
+  }
+
+  void abortWriteTransaction() throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (writeTransaction != null) {
+        writeTransaction.abortTransaction("Explicit abort requested by write-lock manager", new Throwable());
+        writeTransaction = null;
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransaction.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransaction.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransaction.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -11,16 +11,15 @@
  *
  * This file is an original work developed by Netymon Pty Ltd
  * (http://www.netymon.com, mailto:mail at netymon.com). Portions created
- * by Netymon Pty Ltd are Copyright (c) 2006 Netymon Pty Ltd.
+ * by Netymon Pty Ltd are Copyright (c) 2007 Netymon Pty Ltd.
  * All Rights Reserved.
+ *
+ * Migration to interface Copyright (c) 2007 Topaz Foundation
+ * under contract by Andrae Muys (mailto:andrae at netymon.com).
  */
 package org.mulgara.resolver;
 
 // Java 2 enterprise packages
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
-import javax.transaction.Transaction;
 
 // Third party packages
 import org.apache.log4j.Logger;
@@ -34,17 +33,8 @@
 import org.mulgara.query.TuplesException;
 
 /**
- * Responsible for the javax.transaction.Transaction object.
- * Responsibilities
- * Ensuring every begin or resume is followed by either a suspend or an end.
- * Ensuring every suspend or end is preceeded by either a begin or a resume.
- * In conjunction with TransactionalAnswer ensuring that
- * all calls to operations on SubqueryAnswer are preceeded by a successful resume.
- * all calls to operations on SubqueryAnswer conclude with a suspend as the last call prior to returning to the user.
- * Collaborates with DatabaseTransactionManager to determine when to end the transaction.
+ * @created 2007-11-06
  *
- * @created 2006-10-06
- *
  * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
  *
  * @version $Revision: $
@@ -55,682 +45,49 @@
  *
  * @company <a href="mailto:mail at netymon.com">Netymon Pty Ltd</a>
  *
- * @copyright &copy;2006 <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
+ * @copyright &copy;2007 <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
  *
  * @licence Open Software License v3.0
  */
-public class MulgaraTransaction {
+public interface MulgaraTransaction {
+  void reference() throws MulgaraTransactionException;
+  void dereference() throws MulgaraTransactionException;
+
   /**
-   * This is the state machine switch matching these states.
-      switch (state) {
-        case CONSTRUCTEDREF:
-        case CONSTRUCTEDUNREF:
-        case ACTUNREF:
-        case ACTREF:
-        case DEACTREF:
-        case FINISHED:
-        case FAILED:
-      }
+   * Forces the transaction to be abandoned, including bypassing JTA to directly
+   * rollback/abort the underlying store-phases if required.
+   * This this transaction is externally managed this amounts to a heuristic
+   * rollback decision and should be treated as such.
+   *
+   * @return an exception constructed with the provided error-message and cause.
+   * @throws MulgaraTransactionException if a further error is encounted while
+   * attempting to abort.
    */
-  private enum State { CONSTRUCTEDREF, CONSTRUCTEDUNREF, ACTUNREF, ACTREF, DEACTREF, FINISHED, FAILED };
+  MulgaraTransactionException abortTransaction(String errorMessage, Throwable cause) throws MulgaraTransactionException;
 
-  /** Logger.  */
-  private static final Logger logger =
-    Logger.getLogger(MulgaraTransaction.class.getName());
+  void heuristicRollback(String cause) throws MulgaraTransactionException;
 
-  private MulgaraTransactionManager manager;
-  private DatabaseOperationContext context;
-  private Set<EnlistableResource> enlisted;
-
-  private Transaction transaction;
-  private Thread currentThread;
-
-  private ReentrantLock activationMutex;
-
-  private State state;
-  private int inuse;
-  private int using;
-
-  private Throwable rollbackCause;
-
-  public MulgaraTransaction(MulgaraTransactionManager manager, DatabaseOperationContext context)
-      throws IllegalArgumentException {
-    report("Creating Transaction");
-
-    try {
-      if (manager == null) {
-        throw new IllegalArgumentException("Manager null in MulgaraTransaction");
-      } else if (context == null) {
-        throw new IllegalArgumentException("OperationContext null in MulgaraTransaction");
-      }
-      this.manager = manager;
-      this.context = context;
-      this.enlisted = new HashSet<EnlistableResource>();
-      this.activationMutex = new ReentrantLock();
-      this.currentThread = null;
-
-      inuse = 0;
-      using = 0;
-      state = State.CONSTRUCTEDUNREF;
-      rollbackCause = null;
-    } finally {
-      report("Finished Creating Transaction");
-    }
-  }
-
-
-  void activate() throws MulgaraTransactionException {
-//    report("Activating Transaction");
-    try {
-      synchronized (this) {
-        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-      
-      acquireActivationMutex();
-      try {
-        switch (state) {
-          case CONSTRUCTEDUNREF:
-            startTransaction();
-            inuse = 1;
-            state = State.ACTUNREF;
-            try {
-              context.initiate(this);
-            } catch (Throwable th) {
-              throw implicitRollback(th);
-            }
-            break;
-          case CONSTRUCTEDREF:
-            startTransaction();
-            inuse = 1;
-            using = 1;
-            state = State.ACTREF;
-            try {
-              context.initiate(this);
-            } catch (Throwable th) {
-              throw implicitRollback(th);
-            }
-            break;
-          case DEACTREF:
-            resumeTransaction();
-            inuse = 1;
-            state = State.ACTREF;
-            break;
-          case ACTREF:
-          case ACTUNREF:
-            inuse++;
-            break;
-          case FINISHED:
-            throw new MulgaraTransactionException("Attempt to activate terminated transaction");
-          case FAILED:
-            throw new MulgaraTransactionException("Attempt to activate failed transaction", rollbackCause);
-        }
-      } finally {
-        releaseActivationMutex();
-      }
-
-      try {
-        checkActivated();
-      } catch (MulgaraTransactionException em) {
-        throw abortTransaction("Activate failed post-condition check", em);
-      }
-    } catch (MulgaraTransactionException em) {
-      throw em;
-    } catch (Throwable th) {
-      throw abortTransaction("Error activating transaction", th);
-    } finally {
-//      report("Leaving Activate transaction");
-    }
-  }
-
-
-  private void deactivate() throws MulgaraTransactionException {
-//    report("Deactivating transaction");
-
-    try {
-      synchronized (this) {
-        if (currentThread == null) {
-          throw new MulgaraTransactionException("Transaction not associated with thread");
-        } else if (!currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-      
-      acquireActivationMutex();
-      try {
-        switch (state) {
-          case ACTUNREF:
-            if (inuse == 1) {
-              commitTransaction();
-            }
-            inuse--;
-            break;
-          case ACTREF:
-            if (inuse == 1) {
-              suspendTransaction();
-            }
-            inuse--;
-            break;
-          case CONSTRUCTEDREF:
-            throw new MulgaraTransactionException("Attempt to deactivate uninitiated refed transaction");
-          case CONSTRUCTEDUNREF:
-            throw new MulgaraTransactionException("Attempt to deactivate uninitiated transaction");
-          case DEACTREF:
-            throw new IllegalStateException("Attempt to deactivate unactivated transaction");
-          case FINISHED:
-            if (inuse < 0) {
-              errorReport("Activation count failure - too many deacts - in finished transaction", null);
-            } else {
-              inuse--;
-            }
-            break;
-          case FAILED:
-            // Nothing to do here.
-            break;
-        }
-      } finally {
-        releaseActivationMutex();
-      }
-    } catch (MulgaraTransactionException em) {
-      throw em;
-    } catch (Throwable th) {
-      throw abortTransaction("Error deactivating transaction", th);
-    } finally {
-//      report("Leaving Deactivate Transaction");
-    }
-  }
-
-  // Note: The transaction is often not activated when these are called.
-  //       This occurs when setting autocommit, as this creates and
-  //       references a transaction object that won't be started/activated
-  //       until it is first used.
-  void reference() throws MulgaraTransactionException {
-    try {
-      report("Referencing Transaction");
-
-      synchronized (this) {
-        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-
-      switch (state) {
-        case CONSTRUCTEDUNREF:
-          state = State.CONSTRUCTEDREF;
-          break;
-        case ACTREF:
-        case ACTUNREF:
-          using++;
-          state = State.ACTREF;
-          break;
-        case DEACTREF:
-          using++;
-          break;
-        case CONSTRUCTEDREF:
-          throw new MulgaraTransactionException("Attempt to reference uninitated transaction twice");
-        case FINISHED:
-          throw new MulgaraTransactionException("Attempt to reference terminated transaction");
-        case FAILED:
-          throw new MulgaraTransactionException("Attempt to reference failed transaction", rollbackCause);
-      }
-    } catch (MulgaraTransactionException em) {
-      throw em;
-    } catch (Throwable th) {
-      report("Error referencing transaction");
-      throw implicitRollback(th);
-    } finally {
-      report("Leaving Reference Transaction");
-    }
-  }
-
-  void dereference() throws MulgaraTransactionException {
-    report("Dereferencing Transaction");
-    try {
-      synchronized (this) {
-        if (currentThread != null && !currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-
-      switch (state) {
-        case ACTREF:
-          if (using == 1) {
-            state = State.ACTUNREF;
-          }
-          using--;
-          break;
-        case CONSTRUCTEDREF:
-          state = State.CONSTRUCTEDUNREF;
-          break;
-        case FINISHED:
-        case FAILED:
-          if (using < 1) {
-            errorReport("Reference count failure - too many derefs - in finished transaction", null);
-          } else {
-            using--;
-          }
-          break;
-        case ACTUNREF:
-          throw new IllegalStateException("Attempt to dereference unreferenced transaction");
-        case CONSTRUCTEDUNREF:
-          throw new MulgaraTransactionException("Attempt to dereference uninitated transaction");
-        case DEACTREF:
-          throw new IllegalStateException("Attempt to dereference deactivated transaction");
-      }
-    } catch (MulgaraTransactionException em) {
-      throw em;
-    } catch (Throwable th) {
-      throw implicitRollback(th);
-    } finally {
-      report("Dereferenced Transaction");
-    }
-  }
-
-  private void startTransaction() throws MulgaraTransactionException {
-    report("Initiating transaction");
-    try {
-      transaction = manager.transactionStart(this);
-      synchronized (this) {
-        currentThread = Thread.currentThread();
-      }
-    } catch (Throwable th) {
-      throw abortTransaction("Failed to start transaction", th);
-    }
-  }
-
-  private void resumeTransaction() throws MulgaraTransactionException {
-//    report("Resuming transaction");
-    try {
-      manager.transactionResumed(this, transaction);
-      synchronized (this) {
-        currentThread = Thread.currentThread();
-      }
-    } catch (Throwable th) {
-      abortTransaction("Failed to resume transaction", th);
-    }
-  }
-
-  private void suspendTransaction() throws MulgaraTransactionException {
-//    report("Suspending Transaction");
-    try {
-      if (using < 1) {
-        throw implicitRollback(
-            new MulgaraTransactionException("Attempt to suspend unreferenced transaction"));
-      }
-      transaction = manager.transactionSuspended(this);
-      synchronized (this) {
-        currentThread = null;
-      }
-      state = State.DEACTREF;
-    } catch (Throwable th) {
-      throw implicitRollback(th);
-    } finally {
-//      report("Finished suspending transaction");
-    }
-  }
-
-  public void commitTransaction() throws MulgaraTransactionException {
-    report("Committing Transaction");
-    try {
-      transaction.commit();
-    } catch (Throwable th) {
-      throw implicitRollback(th);
-    }
-    try {
-      try {
-        transaction = null;
-      } finally { try {
-        state = State.FINISHED;
-      } finally { try {
-        context.clear();
-      } finally { try {
-        enlisted.clear();
-      } finally { try {
-        manager.transactionComplete(this);
-      } finally { try {
-        manager = null;
-      } finally {
-        report("Committed transaction");
-      } } } } } }
-    } catch (Throwable th) {
-      errorReport("Error cleaning up transaction post-commit", th);
-      throw new MulgaraTransactionException("Error cleaning up transaction post-commit", th);
-    }
-  }
-
   /**
-   * Rollback the transaction.
-   * We don't throw an exception here when transaction fails - this is expected,
-   * after all we requested it.
+   * Execute the specified operation.
    */
-  public void explicitRollback() throws MulgaraTransactionException {
-    synchronized (this) {
-      if (currentThread == null) {
-        throw new MulgaraTransactionException("Transaction failed activation check");
-      } else if (!currentThread.equals(Thread.currentThread())) {
-        throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-      }
-    }
+  void execute(Operation operation,
+               DatabaseMetadata metadata) throws MulgaraTransactionException;
 
-    try {
-      switch (state) {
-        case ACTUNREF:
-        case ACTREF:
-          transaction.rollback();
-          context.clear();
-          enlisted.clear();
-          manager.transactionComplete(this);
-          state = State.FINISHED;
-          break;
-        case DEACTREF:
-          throw new IllegalStateException("Attempt to rollback unactivated transaction");
-        case CONSTRUCTEDREF:
-          throw new MulgaraTransactionException("Attempt to rollback uninitiated ref'd transaction");
-        case CONSTRUCTEDUNREF:
-          throw new MulgaraTransactionException("Attempt to rollback uninitiated unref'd transaction");
-        case FINISHED:
-          throw new MulgaraTransactionException("Attempt to rollback finished transaction");
-        case FAILED:
-          throw new MulgaraTransactionException("Attempt to rollback failed transaction");
-      }
-    } catch (MulgaraTransactionException em) {
-      throw em;
-    } catch (Throwable th) {
-      throw implicitRollback(th);
-    }
-  }
-
   /**
-   * This will endevour to terminate the transaction via a rollback - if this
-   * fails it will abort the transaction.
-   * If the rollback succeeds then this method will return a suitable
-   * MulgaraTransactionException to be thrown by the caller.
-   * If the rollback fails then this method will throw the resulting exception
-   * from abortTransaction().
-   * Post-condition: The transaction is terminated and cleaned up.
+   * Execute the specified operation.
+   * Used by TransactionalAnswer to ensure transactional guarantees are met when
+   * using a result whose transaction may be in a suspended state.
    */
-  MulgaraTransactionException implicitRollback(Throwable cause) throws MulgaraTransactionException {
-    try {
-      report("Implicit Rollback triggered");
+  AnswerOperationResult execute(AnswerOperation ao) throws TuplesException;
 
-      synchronized (this) {
-        if (currentThread == null) {
-          throw new MulgaraTransactionException("Transaction not associated with thread");
-        } else if (!currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-
-      if (rollbackCause != null) {
-        errorReport("Cascading error, transaction already rolled back", cause);
-        errorReport("Cascade error, expected initial cause", rollbackCause);
-
-        return new MulgaraTransactionException("Transaction already in rollback", cause);
-      }
-
-      switch (state) {
-        case ACTUNREF:
-        case ACTREF:
-            rollbackCause = cause;
-            transaction.rollback();
-            transaction = null;
-            context.clear();
-            enlisted.clear();
-            state = State.FAILED;
-            manager.transactionComplete(this);
-            manager = null;
-            return new MulgaraTransactionException("Transaction rollback triggered", cause);
-        case DEACTREF:
-          throw new IllegalStateException("Attempt to rollback deactivated transaction");
-        case CONSTRUCTEDREF:
-          throw new MulgaraTransactionException("Attempt to rollback uninitiated ref'd transaction");
-        case CONSTRUCTEDUNREF:
-          throw new MulgaraTransactionException("Attempt to rollback uninitiated unref'd transaction");
-        case FINISHED:
-          throw new MulgaraTransactionException("Attempt to rollback finished transaction");
-        case FAILED:
-          throw new MulgaraTransactionException("Attempt to rollback failed transaction");
-        default:
-          throw new MulgaraTransactionException("Unknown state");
-      }
-    } catch (Throwable th) {
-      errorReport("Attempt to rollback failed; initiating cause: ", cause);
-      throw abortTransaction("Failed to rollback normally - see log for inititing cause", th);
-    } finally {
-      report("Leaving implicitRollback");
-    }
-  }
-
   /**
-   * Forces the transaction to be abandoned, including bypassing JTA to directly
-   * rollback/abort the underlying store-phases if required.
-   * Heavilly nested try{}finally{} should guarentee that even JVM errors should
-   * not prevent this function from cleaning up anything that can be cleaned up.
-   * We have to delegate to the OperationContext the abort() on the resolvers as
-   * only it has full knowledge of which resolvers are associated with this
-   * transaction.
+   * Used by the TransactionCoordinator/Manager.
    */
-  MulgaraTransactionException abortTransaction(String errorMessage, Throwable cause)
-      throws MulgaraTransactionException {
-    // We need to notify the manager here - this is serious, we
-    // need to rollback this transaction, but if we have reached here
-    // we have failed to obtain a valid transaction to rollback!
-    try {
-      try {
-        errorReport(errorMessage + " - Aborting", cause);
-      } finally { try {
-        if (transaction != null) {
-          transaction.rollback();
-        }
-      } finally { try {
-        manager.transactionAborted(this);
-      } finally { try {
-        abortEnlistedResources();
-      } finally { try {
-        context.clear();
-      } finally { try {
-        enlisted.clear();
-      } finally { try {
-        transaction = null;
-      } finally { try {
-        manager = null;
-      } finally {
-        state = State.FAILED;
-      } } } } } } } }
-      return new MulgaraTransactionException(errorMessage + " - Aborting", cause);
-    } catch (Throwable th) {
-      throw new MulgaraTransactionException(errorMessage + " - Failed to abort cleanly", th);
-    } finally {
-      report("Leaving abortTransaction");
-    }
-  }
+  void execute(TransactionOperation to) throws MulgaraTransactionException;
 
   /**
-   * Used to bypass JTA and explicitly abort resources behind the scenes.
+   * enlist an XAResource in this transaction - includes an extra method
+   * abort().
    */
-  private void abortEnlistedResources() {
-    for (EnlistableResource e : enlisted) {
-      try {
-        e.abort();
-      } catch (Throwable th) {
-        try {
-          errorReport("Error aborting enlistable resource", th);
-        } catch (Throwable ignore) { }
-      }
-    }
-  }
-
-  void execute(Operation operation,
-               ResolverSessionFactory resolverSessionFactory, // FIXME: We shouldn't need this. - only used for backup and restore operations.
-               DatabaseMetadata metadata) throws MulgaraTransactionException {
-    report("Executing Operation");
-    try {
-      activate();
-      try {
-        operation.execute(context,
-                          context.getSystemResolver(),
-                          resolverSessionFactory,
-                          metadata);
-      } catch (Throwable th) {
-        throw implicitRollback(th);
-      } finally {
-        deactivate();
-      }
-    } finally {
-      report("Executed Operation");
-    }
-  }
-
-  AnswerOperationResult execute(AnswerOperation ao) throws TuplesException {
-    debugReport("Executing AnswerOperation");
-    try {
-      activate();
-      try {
-        ao.execute();
-        return ao.getResult();
-      } catch (Throwable th) {
-        throw implicitRollback(th);
-      } finally {
-        deactivate();
-      }
-    } catch (MulgaraTransactionException em) {
-      throw new TuplesException("Transaction error", em);
-    } finally {
-      debugReport("Executed AnswerOperation");
-    }
-  }
-
-
-  void execute(TransactionOperation to) throws MulgaraTransactionException {
-    report("Executing TransactionOperation");
-    try {
-      activate();
-      try {
-        to.execute();
-      } catch (Throwable th) {
-        throw implicitRollback(th);
-      } finally {
-        deactivate();
-      }
-    } finally {
-      report("Executed TransactionOperation");
-    }
-  }
-
-  public void enlist(EnlistableResource enlistable) throws MulgaraTransactionException {
-    try {
-      synchronized (this) {
-        if (currentThread == null) {
-          throw new MulgaraTransactionException("Transaction not associated with thread");
-        } else if (!currentThread.equals(Thread.currentThread())) {
-          throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-        }
-      }
-
-      if (enlisted.contains(enlistable)) {
-        return;
-      }
-
-      switch (state) {
-        case ACTUNREF:
-        case ACTREF:
-          transaction.enlistResource(enlistable.getXAResource());
-          enlisted.add(enlistable);
-          break;
-        case CONSTRUCTEDREF:
-          throw new MulgaraTransactionException("Attempt to enlist resource in uninitated ref'd transaction");
-        case CONSTRUCTEDUNREF:
-          throw new MulgaraTransactionException("Attempt to enlist resource in uninitated unref'd transaction");
-        case DEACTREF:
-          throw new MulgaraTransactionException("Attempt to enlist resource in unactivated transaction");
-        case FINISHED:
-          throw new MulgaraTransactionException("Attempt to enlist resource in finished transaction");
-        case FAILED:
-          throw new MulgaraTransactionException("Attempt to enlist resource in failed transaction");
-      }
-    } catch (Throwable th) {
-      throw implicitRollback(th);
-    }
-  }
-
-  //
-  // Used internally
-  //
-
-  private void checkActivated() throws MulgaraTransactionException {
-    synchronized (this) {
-      if (currentThread == null) {
-        throw new MulgaraTransactionException("Transaction not associated with thread");
-      } else if (!currentThread.equals(Thread.currentThread())) {
-        throw new MulgaraTransactionException("Concurrent access attempted to transaction: Transaction has NOT been rolledback.");
-      }
-    }
-
-    switch (state) {
-      case ACTUNREF:
-      case ACTREF:
-        if (inuse < 0 || using < 0) {
-          throw new MulgaraTransactionException("Reference Failure, using: " + using + ", inuse: " + inuse);
-        }
-        return;
-      case CONSTRUCTEDREF:
-        throw new MulgaraTransactionException("Transaction (ref) uninitiated");
-      case CONSTRUCTEDUNREF:
-        throw new MulgaraTransactionException("Transaction (unref) uninitiated");
-      case DEACTREF:
-        throw new MulgaraTransactionException("Transaction deactivated");
-      case FINISHED:
-        throw new MulgaraTransactionException("Transaction is terminated");
-      case FAILED:
-        throw new MulgaraTransactionException("Transaction is failed", rollbackCause);
-    }
-  }
-
-  private void acquireActivationMutex() {
-    activationMutex.lock();
-  }
-
-  private void releaseActivationMutex() {
-    activationMutex.unlock();
-  }
-
-  protected void finalize() {
-    report("GC-finalize");
-    if (state != State.FINISHED && state != State.FAILED) {
-      errorReport("Finalizing incomplete transaction - aborting...", null);
-      try {
-        abortTransaction("Transaction finalized while still valid", new Throwable());
-      } catch (Throwable th) {
-        errorReport("Attempt to abort transaction from finalize failed", th);
-      }
-    }
-
-    if (state != State.FAILED && (inuse != 0 || using != 0)) {
-      errorReport("Reference counting error in transaction", null);
-    }
-
-    if (manager != null || transaction != null) {
-      errorReport("Transaction not terminated properly", null);
-    }
-  }
-
-  private void report(String desc) {
-    if (logger.isInfoEnabled()) {
-      logger.info(desc + ": " + System.identityHashCode(this) + ", state=" + state +
-          ", inuse=" + inuse + ", using=" + using);
-    }
-  }
-
-  private void debugReport(String desc) {
-    if (logger.isDebugEnabled()) {
-      logger.debug(desc + ": " + System.identityHashCode(this) + ", state=" + state +
-          ", inuse=" + inuse + ", using=" + using);
-    }
-  }
-
-  private void errorReport(String desc, Throwable cause) {
-    logger.error(desc + ": " + System.identityHashCode(this) + ", state=" + state +
-        ", inuse=" + inuse + ", using=" + using, cause != null ? cause : new Throwable());
-  }
+  public void enlist(EnlistableResource enlistable) throws MulgaraTransactionException;
 }

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionFactory.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionFactory.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionFactory.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,249 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com). Portions created
+ * by Netymon Pty Ltd are Copyright (c) 2006 Netymon Pty Ltd.
+ * All Rights Reserved.
+ *
+ * Derivation from MulgaraTransactionManager Copyright (c) 2007 Topaz
+ * Foundation under contract by Andrae Muys (mailto:andrae at netymon.com).
+ */
+
+package org.mulgara.resolver;
+
+// Java2 packages
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.server.Session;
+import org.mulgara.transaction.TransactionManagerFactory;
+
+/**
+ * Manages transactions within Mulgara.
+ *
+ * see http://mulgara.org/confluence/display/dev/Transaction+Architecture
+ *
+ * Maintains association between Answer's and TransactionContext's.
+ * Manages tracking the ownership of the write-lock.
+ * Maintains the write-queue and any timeout algorithm desired.
+ * Provides new/existing TransactionContext's to DatabaseSession on request.
+ *    Note: Returns new context unless Session is currently in a User Demarcated Transaction.
+ * 
+ * @created 2006-10-06
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ *
+ * @copyright &copy;2006 <a href="http://www.netymon.com/">Netymon Pty Ltd</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public abstract class MulgaraTransactionFactory {
+  private static final Logger logger =
+    Logger.getLogger(MulgaraTransactionFactory.class.getName());
+
+  protected final MulgaraTransactionManager manager;
+  
+  /**
+   * Contains a reference the the current writing transaction IFF it is managed
+   * by this factory.  If there is no current writing transaction, or if the
+   * writing transaction is managed by a different factory then it is null.
+   */
+  protected MulgaraTransaction writeTransaction;
+
+  private ReentrantLock mutex;
+
+  protected MulgaraTransactionFactory(MulgaraTransactionManager manager) {
+    this.manager = manager;
+    this.mutex = new ReentrantLock();
+    this.writeTransaction = null;
+  }
+
+
+  /**
+   * Obtain a transaction context associated with a DatabaseSession.
+   *
+   * Either returns the existing context if:
+   * a) we are currently within a recursive call while under implicit XA control
+   * or
+   * b) we are currently within an active user demarcated XA.
+   * otherwise creates a new transaction context and associates it with the
+   * session.
+   */
+  public abstract MulgaraTransaction getTransaction(final DatabaseSession session, boolean write)
+      throws MulgaraTransactionException;
+  
+  protected abstract Set<? extends MulgaraTransaction> getTransactionsForSession(DatabaseSession session);
+
+  /**
+   * Rollback, or abort all transactions associated with a DatabaseSession.
+   *
+   * Will only abort the transaction if the rollback attempt fails.
+   */
+  public void closingSession(DatabaseSession session) throws MulgaraTransactionException {
+    acquireMutex();
+    logger.debug("Cleaning up any stale transactions on session close");
+    try {
+      Map<MulgaraTransaction, Throwable> requiresAbort = new HashMap<MulgaraTransaction, Throwable>();
+      try {
+        Throwable error = null;
+
+        if (manager.isHoldingWriteLock(session)) {
+          logger.debug("Session holds write-lock");
+          try {
+            if (writeTransaction != null) {
+              try {
+                logger.warn("Terminating session while holding writelock:" + session + ": " + writeTransaction);
+                writeTransaction.execute(new TransactionOperation() {
+                    public void execute() throws MulgaraTransactionException {
+                      writeTransaction.heuristicRollback("Session closed while holding write lock");
+                    }
+                });
+              } catch (Throwable th) {
+                if (writeTransaction != null) {
+                  requiresAbort.put(writeTransaction, th);
+                  error = th;
+                }
+              } finally {
+                writeTransaction = null;
+              }
+            }
+          } finally {
+            manager.releaseWriteLock(session);
+          }
+        } else {
+          logger.debug("Session does not hold write-lock");
+        }
+
+        for (MulgaraTransaction transaction : getTransactionsForSession(session)) {
+          try {
+            // This is final so we can create the closure.
+            final MulgaraTransaction xa = transaction;
+            transaction.execute(new TransactionOperation() {
+                public void execute() throws MulgaraTransactionException {
+                  xa.heuristicRollback("Rollback due to session close");
+                }
+            });
+          } catch (Throwable th) {
+            requiresAbort.put(transaction, th);
+            if (error == null) {
+              error = th;
+            }
+          }
+        }
+
+        if (error != null) {
+          throw new MulgaraTransactionException("Heuristic rollback failed on session close", error);
+        }
+      } finally {
+        try {
+          abortTransactions(requiresAbort);
+        } catch (Throwable th) {
+          try {
+            logger.error("Error aborting transactions after heuristic rollback failure on session close", th);
+          } catch (Throwable throw_away) { }
+        }
+      }
+    } finally {
+      releaseMutex();
+    }
+  }
+
+  /**
+   * Abort as many of the transactions as we can.
+   */
+  protected void abortTransactions(Map<MulgaraTransaction, Throwable> requiresAbort) {
+    try {
+      if (!requiresAbort.isEmpty()) {
+        // At this point the originating exception has been thrown in the caller
+        // so we attempt to ensure it doesn't get superseeded by anything that
+        // might be thrown here while logging any errors.
+        try {
+          logger.error("Heuristic Rollback Failed on session close- aborting");
+        } catch (Throwable throw_away) { } // Logging difficulties.
+
+        try {
+          for (MulgaraTransaction transaction : requiresAbort.keySet()) {
+            try {
+              transaction.abortTransaction("Heuristic Rollback failed on session close",
+                  requiresAbort.get(transaction));
+            } catch (Throwable th) {
+              try {
+                logger.error("Error aborting transaction after heuristic rollback failure on session close", th);
+              } catch (Throwable throw_away) { }
+            }
+          }
+        } catch (Throwable th) {
+          try {
+            logger.error("Loop error while aborting transactions after heuristic rollback failure on session close", th);
+          } catch (Throwable throw_away) { }
+        }
+      }
+    } catch (Throwable th) {
+      try {
+        logger.error("Unidentified error while aborting transactions after heuristic rollback failure on session close", th);
+      } catch (Throwable throw_away) { }
+    }
+  }
+
+  /**
+   * Used to replace the built in monitor to allow it to be properly released
+   * during potentially blocking operations.  All potentially blocking
+   * operations involve writes, so in these cases the write-lock is reserved
+   * allowing the mutex to be safely released and then reobtained after the
+   * blocking operation concludes.
+   */
+  protected void acquireMutex() {
+    mutex.lock();
+  }
+
+
+  protected void releaseMutex() {
+    if (!mutex.isHeldByCurrentThread()) {
+      throw new IllegalStateException("Attempt to release mutex without holding mutex");
+    }
+
+    mutex.unlock();
+  }
+
+  protected void runWithoutMutex(TransactionOperation proc) throws MulgaraTransactionException {
+    if (!mutex.isHeldByCurrentThread()) {
+      throw new IllegalStateException("Attempt to run procedure without holding mutex");
+    }
+    int holdCount = mutex.getHoldCount();
+    for (int i = 0; i < holdCount; i++) {
+      mutex.unlock();
+    }
+    try {
+      proc.execute();
+    } finally {
+      for (int i = 0; i < holdCount; i++) {
+        mutex.lock();
+      }
+    }
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionManager.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionManager.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraTransactionManager.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -13,40 +13,34 @@
  * (http://www.netymon.com, mailto:mail at netymon.com). Portions created
  * by Netymon Pty Ltd are Copyright (c) 2006 Netymon Pty Ltd.
  * All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Refactoring to focus on write-lock management contributed by Netymon
+ *   Pty Ltd on behalf of Topaz Foundation under contract.
  */
 
 package org.mulgara.resolver;
 
 // Java2 packages
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
 
 // Third party packages
 import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.MulgaraTransactionException;
-import org.mulgara.server.Session;
 import org.mulgara.transaction.TransactionManagerFactory;
 
 /**
- * Manages transactions within Mulgara.
+ * Manages the Write-Lock.
  *
- * see http://mulgara.org/confluence/display/dev/Transaction+Architecture
- *
- * Maintains association between Answer's and TransactionContext's.
  * Manages tracking the ownership of the write-lock.
- * Maintains the write-queue and any timeout algorithm desired.
  * Provides new/existing TransactionContext's to DatabaseSession on request.
  *    Note: Returns new context unless Session is currently in a User Demarcated Transaction.
- * 
+ * Provides a facility to trigger a heuristic rollback of any transactions still
+ *   valid on session close.
+ * Maintains the write-queue and any timeout algorithm desired.
  *
  * @created 2006-10-06
  *
@@ -71,457 +65,97 @@
     Logger.getLogger(MulgaraTransactionManager.class.getName());
 
   // Write lock is associated with a session.
-  private Session currentWritingSession;
-  private MulgaraTransaction userTransaction;
-  private boolean autoCommit;
+  private DatabaseSession sessionHoldingWriteLock;
 
-  private ReentrantLock mutex;
-  private Condition writeLockCondition;
-  private Condition reserveCondition;
-  private Thread reservingThread;
+  // Used to support write-lock reservation.
+  private DatabaseSession sessionReservingWriteLock;
 
-  /** Set of sessions whose transactions have been rolledback.*/
-  private Set<Session> failedSessions;
+  // Used to synchronize access to other fields.
+  private final ReentrantLock mutex;
+  private final Condition writeLockCondition;
 
-  /**
-   * Map from transaction to initiating session.
-   * FIXME: This is only required for checking while we wait for 1-N.
-   *        Remove once 1-N is implemented.
-   */
-  private Map<MulgaraTransaction, Session> sessions;
+  private final MulgaraInternalTransactionFactory internalFactory;
+  private final MulgaraExternalTransactionFactory externalFactory;
 
-  /**
-   * Map from initiating session to set of transactions.
-   * Used to clean-up transactions upon session close.
-   */
-  private Map<Session, Set<MulgaraTransaction>> transactions;
-
-  /** Map of threads to active transactions. */
-  private Map<Thread, MulgaraTransaction> activeTransactions;
-
-  private final TransactionManager transactionManager;
-
   public MulgaraTransactionManager(TransactionManagerFactory transactionManagerFactory) {
-    this.currentWritingSession = null;
-    this.userTransaction = null;
-    this.autoCommit = true;
+    this.sessionHoldingWriteLock = null;
+    this.sessionReservingWriteLock = null;
     this.mutex = new ReentrantLock();
     this.writeLockCondition = this.mutex.newCondition();
-    this.reserveCondition = this.mutex.newCondition();
-    this.reservingThread = null;
 
-    this.failedSessions = new HashSet<Session>();
-    this.sessions = new HashMap<MulgaraTransaction, Session>();
-    this.transactions = new HashMap<Session, Set<MulgaraTransaction>>();
-    this.activeTransactions = new HashMap<Thread, MulgaraTransaction>();
-
-    this.transactionManager = transactionManagerFactory.newTransactionManager();
+    this.internalFactory = new MulgaraInternalTransactionFactory(this, transactionManagerFactory);
+    this.externalFactory = new MulgaraExternalTransactionFactory(this);
   }
 
-  /**
-   * Allows DatabaseSession to initiate/obtain a transaction.
-   * <ul>
-   * <li>If the Session holds the write lock, return the current Write-Transaction.</li>
-   * <li>If the Session does not hold the write lock and requests a read-only transaction,
-   *     create a new ro-transaction object and return it.</li>
-   * <li>If the Session does not hold the write lock and requests a read-write transaction,
-   *     obtain the write-lock, create a new transaction object and return it.</li>
-   * </ul>
-   */
-  public MulgaraTransaction getTransaction(DatabaseSession session, boolean write) throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      if (session == currentWritingSession) {
-        return userTransaction;
-      } 
 
-      try {
-        MulgaraTransaction transaction = write ?
-            obtainWriteLock(session) :
-            new MulgaraTransaction(this, session.newOperationContext(false));
+  MulgaraInternalTransactionFactory getInternalFactory() {
+    return internalFactory;
+  }
 
-        sessions.put(transaction, session);
-
-        if (!transactions.containsKey(session)) {
-          transactions.put(session, new HashSet<MulgaraTransaction>());
-        }
-        transactions.get(session).add(transaction);
-
-        return transaction;
-      } catch (MulgaraTransactionException em) {
-        throw em;
-      } catch (Exception e) {
-        throw new MulgaraTransactionException("Error creating transaction", e);
-      }
-    } finally {
-      releaseMutex();
-    }
+  MulgaraExternalTransactionFactory getExternalFactory() {
+    return externalFactory;
   }
 
 
   /** 
    * Obtains the write lock.
-   * Must hold readMutex on entry - but will drop readMutex if
    */
-  private MulgaraTransaction obtainWriteLock(DatabaseSession session)
-      throws MulgaraTransactionException {
-    while (writeLockHeld() || writeLockReserved()) {
-      try {
-        writeLockCondition.await();
-      } catch (InterruptedException ei) {
-        throw new MulgaraTransactionException("Interrupted while waiting for write lock", ei);
-      }
-    }
-
-    try {
-      currentWritingSession = session;
-      userTransaction = new MulgaraTransaction(this, session.newOperationContext(true));
-      return userTransaction;
-    } catch (Throwable th) {
-      releaseWriteLock();
-      throw new MulgaraTransactionException("Error while obtaining write-lock", th);
-    }
-  }
-
-  private void releaseWriteLock() {
-    // Calling this method multiple times is safe as the lock cannot be obtained
-    // between calls as this method is private, and all calling methods are
-    // synchronized.
-    currentWritingSession = null;
-    userTransaction = null;
-    writeLockCondition.signal();
-  }
-
-  public void commit(DatabaseSession session) throws MulgaraTransactionException {
+  void obtainWriteLock(DatabaseSession session) throws MulgaraTransactionException {
     acquireMutex();
     try {
-      reserveWriteLock();
-      if (failedSessions.contains(session)) {
-        throw new MulgaraTransactionException("Attempting to commit failed exception");
-      } else if (session != currentWritingSession) {
-        throw new MulgaraTransactionException(
-            "Attempting to commit while not the current writing transaction");
+      if (sessionHoldingWriteLock == session) {
+        return;
       }
 
-      setAutoCommit(session, true);
-      setAutoCommit(session, false);
-    } finally {
-      releaseMutex();
-    }
-  }
-
-
-  /**
-   * This is an explicit, user-specified rollback.
-   * 
-   * This needs to be distinguished from an implicit rollback triggered by failure.
-   */
-  public void rollback(DatabaseSession session) throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      reserveWriteLock();
-      if (session == currentWritingSession) {
+      while (writeLockHeld() || (writeLockReserved() && !writeLockReserved(session))) {
         try {
-          userTransaction.execute(new TransactionOperation() {
-            public void execute() throws MulgaraTransactionException {
-              userTransaction.explicitRollback();
-            }
-          });
-          if (userTransaction != null) {
-            // transaction referenced by something - need to explicitly end it.
-            userTransaction.abortTransaction("Rollback failed",
-                new MulgaraTransactionException("Rollback failed to terminate write transaction"));
-          }
-        } finally {
-          failedSessions.add(session);
-          releaseWriteLock();
-          setAutoCommit(session, false);
+          writeLockCondition.await();
+        } catch (InterruptedException ei) {
+          throw new MulgaraTransactionException("Interrupted while waiting for write lock", ei);
         }
-      } else if (failedSessions.contains(session)) {
-        failedSessions.remove(session);
-        setAutoCommit(session, false);
-      } else {
-        throw new MulgaraTransactionException(
-            "Attempt to rollback while not in the current writing transaction");
       }
-    } finally {
-      releaseMutex();
-    }
-  }
 
-  public void setAutoCommit(DatabaseSession session, boolean autoCommit)
-      throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      if (session == currentWritingSession && failedSessions.contains(session)) {
-        userTransaction.abortTransaction("Session failed and transaction not finalized",
-            new MulgaraTransactionException("Failed Session in setAutoCommit"));
+      if (logger.isDebugEnabled()) {
+        logger.debug("Obtaining write lock", new Throwable());
       }
-
-      if (session == currentWritingSession || failedSessions.contains(session)) {
-        if (autoCommit) {
-          // AutoCommit off -> on === branch on current state of transaction.
-          if (session == currentWritingSession) {
-            // Within active transaction - commit and finalise.
-            try {
-              runWithoutMutex(new TransactionOperation() {
-                public void execute() throws MulgaraTransactionException {
-                  userTransaction.execute(new TransactionOperation() {
-                    public void execute() throws MulgaraTransactionException {
-                      userTransaction.dereference();
-                      userTransaction.commitTransaction();
-                    }
-                  });
-                }
-              });
-            } finally {
-              releaseWriteLock();
-              this.autoCommit = true;
-            }
-          } else if (failedSessions.contains(session)) {
-            // Within failed transaction - cleanup.
-            failedSessions.remove(session);
-          }
-        } else {
-          logger.info("Attempt to set autocommit false twice");
-          // AutoCommit off -> off === no-op. Log info.
-        }
-      } else {
-        if (autoCommit) {
-          // AutoCommit on -> on === no-op.  Log info.
-          logger.info("Attempting to set autocommit true without setting it false");
-        } else {
-          // AutoCommit on -> off == Start new transaction.
-          userTransaction = getTransaction(session, true);
-          userTransaction.reference();
-          this.autoCommit = false;
-        }
-      }
+      sessionHoldingWriteLock = session;
     } finally {
       releaseMutex();
     }
   }
 
-  public void rollbackCurrentTransactions(Session session) throws MulgaraTransactionException {
+  boolean isHoldingWriteLock(DatabaseSession session) {
     acquireMutex();
     try {
-      try {
-        if (failedSessions.contains(session)) {
-          failedSessions.remove(session);
-          return;
-        }
-
-        Throwable error = null;
-
-        try {
-          if (session == currentWritingSession) {
-            logger.warn("Terminating session while holding writelock:" + session + ": " + userTransaction);
-            userTransaction.execute(new TransactionOperation() {
-                public void execute() throws MulgaraTransactionException {
-                  throw new MulgaraTransactionException("Terminating session while holding writelock");
-                }
-            });
-          }
-        } catch (Throwable th) {
-          error = th;
-        }
-
-        if (transactions.containsKey(session)) {
-          for (MulgaraTransaction transaction : transactions.get(session)) {
-            try {
-              transaction.execute(new TransactionOperation() {
-                public void execute() throws MulgaraTransactionException {
-                  throw new MulgaraTransactionException("Rolling back transactions due to session close");
-                }
-              });
-            } catch (MulgaraTransactionException em) {
-              // ignore.
-            } catch (Throwable th) {
-              if (error == null) {
-                error = th;
-              }
-            }
-          }
-        }
-
-        if (error != null) {
-          if (error instanceof MulgaraTransactionException) {
-            throw (MulgaraTransactionException)error;
-          } else {
-            throw new MulgaraTransactionException("Error in rollback on session close", error);
-          }
-        }
-      } finally {
-        if (transactions.containsKey(session)) {
-          logger.error("Error in transaction rollback due to session close - aborting");
-          abortCurrentTransactions(session);
-        }
-      }
+      return sessionHoldingWriteLock == session;
     } finally {
       releaseMutex();
     }
   }
 
-  private void abortCurrentTransactions(Session session) throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      try {
-        Throwable error = null;
-        for (MulgaraTransaction transaction : transactions.get(session)) {
-          try {
-            transaction.abortTransaction("Transaction still valid on session close", new Throwable());
-          } catch (Throwable th) {
-            try {
-              if (error == null) {
-                error = th;
-              }
-            } catch (Throwable throw_away) {}
-          }
-        }
 
-        if (error != null) {
-          if (error instanceof MulgaraTransactionException) {
-            throw (MulgaraTransactionException)error;
-          } else {
-            throw new MulgaraTransactionException("Error in rollback on session close", error);
-          }
-        }
-      } finally {
-        if (session == currentWritingSession) {
-          logger.error("Failed to abort write-transaction on session close - Server restart required");
-        }
-      }
-    } finally {
-      releaseMutex();
-    }
-  }
-
-  //
-  // Transaction livecycle callbacks.
-  //
-
-  public Transaction transactionStart(MulgaraTransaction transaction) throws MulgaraTransactionException {
+  void releaseWriteLock(DatabaseSession session) throws MulgaraTransactionException {
     acquireMutex();
     try {
-      try {
-        logger.info("Beginning Transaction");
-        if (activeTransactions.get(Thread.currentThread()) != null) {
-          throw new MulgaraTransactionException(
-              "Attempt to start transaction in thread with exiting active transaction.");
-        } else if (activeTransactions.containsValue(transaction)) {
-          throw new MulgaraTransactionException("Attempt to start transaction twice");
-        }
-
-        transactionManager.begin();
-        Transaction jtaTrans = transactionManager.getTransaction();
-
-        activeTransactions.put(Thread.currentThread(), transaction);
-
-        return jtaTrans;
-      } catch (Exception e) {
-        throw new MulgaraTransactionException("Transaction Begin Failed", e);
+      if (sessionHoldingWriteLock == null) {
+        return;
       }
-    } finally {
-      releaseMutex();
-    }
-  }
-
-  public void transactionResumed(MulgaraTransaction transaction, Transaction jtaXA) 
-      throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      if (activeTransactions.get(Thread.currentThread()) != null) {
-        throw new MulgaraTransactionException(
-            "Attempt to resume transaction in already activated thread");
-      } else if (activeTransactions.containsValue(transaction)) {
-        throw new MulgaraTransactionException("Attempt to resume active transaction");
+      if (sessionHoldingWriteLock != session) {
+        throw new MulgaraTransactionException("Attempted to release write lock being held by another session");
       }
-      
-      try {
-        transactionManager.resume(jtaXA);
-        activeTransactions.put(Thread.currentThread(), transaction);
-      } catch (Exception e) {
-        throw new MulgaraTransactionException("Resume Failed", e);
+      if (logger.isDebugEnabled()) {
+        logger.debug("Releasing writelock", new Throwable());
       }
+      sessionHoldingWriteLock = null;
+      writeLockCondition.signal();
     } finally {
       releaseMutex();
     }
   }
 
-  public Transaction transactionSuspended(MulgaraTransaction transaction)
-      throws MulgaraTransactionException {
-    acquireMutex();
-    try {
-      try {
-        if (transaction != activeTransactions.get(Thread.currentThread())) {
-          throw new MulgaraTransactionException(
-              "Attempt to suspend transaction from outside thread");
-        }
 
-        if (autoCommit && transaction == userTransaction) {
-          logger.error("Attempt to suspend write transaction without setting AutoCommit Off");
-          throw new MulgaraTransactionException(
-              "Attempt to suspend write transaction without setting AutoCommit Off");
-        }
-
-        Transaction xa = transactionManager.suspend();
-        activeTransactions.remove(Thread.currentThread());
-
-        return xa;
-      } catch (Throwable th) {
-        logger.error("Attempt to suspend failed", th);
-        try {
-          transactionManager.setRollbackOnly();
-        } catch (Throwable t) {
-          logger.error("Attempt to setRollbackOnly() failed", t);
-        }
-        throw new MulgaraTransactionException("Suspend failed", th);
-      }
-    } finally {
-      releaseMutex();
-    }
-  }
-
-  public void transactionComplete(MulgaraTransaction transaction) {
-    acquireMutex();
-    try {
-      if (transaction == userTransaction) {
-        releaseWriteLock();
-      }
-
-      activeTransactions.remove(Thread.currentThread());
-      Session session = (Session)sessions.get(transaction);
-      sessions.remove(transaction);
-      transactions.remove(session);
-    } finally {
-      releaseMutex();
-    }
-  }
-
-  public void transactionAborted(MulgaraTransaction transaction) {
-    acquireMutex();
-    try {
-      try {
-        // Make sure this cleans up the transaction metadata - this transaction is DEAD!
-        if (transaction == userTransaction) {
-          failedSessions.add(currentWritingSession);
-        }
-        transactionComplete(transaction);
-      } catch (Throwable th) {
-        // FIXME: This should probably abort the entire server after logging the error!
-        logger.error("Error managing transaction abort", th);
-      }
-    } finally {
-      releaseMutex();
-    }
-  }
-
   public void setTransactionTimeout(int transactionTimeout) {
-    try {
-      transactionManager.setTransactionTimeout(transactionTimeout);
-    } catch (SystemException es) {
-      logger.warn("Unable to set transaction timeout: " + transactionTimeout, es);
-    }
+    internalFactory.setTransactionTimeout(transactionTimeout);
   }
 
   /**
@@ -538,33 +172,51 @@
 
   /**
    * Used to reserve the write lock during a commit or rollback.
+   * Should only be used by a transaction manager.
    */
-  private void reserveWriteLock() throws MulgaraTransactionException {
-    if (!mutex.isHeldByCurrentThread()) {
-      throw new IllegalStateException("Attempt to set modify without holding mutex");
-    }
+  void reserveWriteLock(DatabaseSession session) throws MulgaraTransactionException {
+    acquireMutex();
+    try {
+      if (session != sessionReservingWriteLock && session != sessionHoldingWriteLock) {
+        throw new IllegalStateException("Attempt to reserve writelock without holding writelock");
+      }
+      if (session != sessionReservingWriteLock && sessionReservingWriteLock != null) {
+        throw new IllegalStateException("Attempt to reserve writelock when writelock already reserved");
+      }
 
-    if (Thread.currentThread().equals(reservingThread)) {
-      return;
+      sessionReservingWriteLock = session;
+    } finally {
+      releaseMutex();
     }
+  }
 
-    while (reservingThread != null) {
-      try {
-        reserveCondition.await();
-      } catch (InterruptedException ei) {
-        throw new MulgaraTransactionException("Thread interrupted while reserving write lock", ei);
-      }
-    }
-    reservingThread = Thread.currentThread();
+  boolean writeLockReserved() {
+    return sessionReservingWriteLock != null;
   }
 
-  private boolean writeLockReserved() {
-    // TRUE iff there is a reserving thread AND it is different thread to the current thread.
-    return reservingThread != null && !Thread.currentThread().equals(reservingThread);
+  boolean writeLockReserved(DatabaseSession session) {
+    return session == sessionReservingWriteLock;
   }
 
+  void releaseReserve(DatabaseSession session) {
+    acquireMutex();
+    try {
+      if (!writeLockReserved()) {
+        return;
+      }
+      if (!writeLockReserved(session)) {
+        throw new IllegalStateException("Attempt to release reserve without holding reserve");
+      }
+
+      sessionReservingWriteLock = null;
+      writeLockCondition.signal();
+    } finally {
+      releaseMutex();
+    }
+  }
+
   private boolean writeLockHeld() {
-    return currentWritingSession != null;
+    return sessionHoldingWriteLock != null;
   }
 
   private void releaseMutex() {
@@ -572,28 +224,59 @@
       throw new IllegalStateException("Attempt to release mutex without holding mutex");
     }
 
-    if (mutex.getHoldCount() == 1 && Thread.currentThread().equals(reservingThread)) {
-      reservingThread = null;
-      reserveCondition.signal();
-    }
-
     mutex.unlock();
   }
 
-  private void runWithoutMutex(TransactionOperation proc) throws MulgaraTransactionException {
-    if (!mutex.isHeldByCurrentThread()) {
-      throw new IllegalStateException("Attempt to run procedure without holding mutex");
+  public void closingSession(DatabaseSession session) throws MulgaraTransactionException {
+    // Calls to final fields do not require mutex.  As both of these calls
+    // potentially call back into the manager, calling these while holding the
+    // lock can invalidate lock-ordering and result in a deadlock.
+    Throwable error = null;
+    try {
+      internalFactory.closingSession(session);
+    } catch (Throwable th) {
+      logger.error("Error signalling session-close to internal xa-factory", th);
+      error = (error == null) ? th : error;
     }
-    int holdCount = mutex.getHoldCount();
-    for (int i = 0; i < holdCount; i++) {
-      mutex.unlock();
+
+    try {
+      externalFactory.closingSession(session);
+    } catch (Throwable th) {
+      logger.error("Error signalling session-close to external xa-factory", th);
+      error = (error == null) ? th : error;
     }
+
+    // This code should not be required, but is there to ensure the manager is
+    // reset regardless of errors in the factories.
+    acquireMutex();
     try {
-      proc.execute();
-    } finally {
-      for (int i = 0; i < holdCount; i++) {
-        mutex.lock();
+      if (writeLockReserved(session)) {
+        try {
+          releaseReserve(session);
+        } catch (Throwable th) {
+          logger.error("Error releasing reserve on force-close", th);
+          error = (error == null) ? th : error;
+        }
       }
+
+      if (isHoldingWriteLock(session)) {
+        try {
+          releaseWriteLock(session);
+        } catch (Throwable th) {
+          logger.error("Error releasing write-lock on force-close", th);
+          error = (error == null) ? th : error;
+        }
+      }
+
+      if (error != null) {
+        if (error instanceof MulgaraTransactionException) {
+          throw (MulgaraTransactionException)error;
+        } else {
+          throw new MulgaraTransactionException("Error force releasing write-lock", error);
+        }
+      }
+    } finally {
+      releaseMutex();
     }
   }
 }

Copied: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java (from rev 722, trunk/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/MulgaraXAResourceContext.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,536 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com) under contract to 
+ * Topaz Foundation. Portions created under this contract are
+ * Copyright (c) 2007 Topaz Foundation
+ * All Rights Reserved.
+ */
+
+package org.mulgara.resolver;
+
+// Java2 packages
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.MulgaraTransactionException;
+import org.mulgara.server.ResourceManagerInstanceAdaptor;
+import org.mulgara.util.Assoc1toNMap;
+
+/**
+ * Provides an external JTA-compliant TransactionManager with the ability to
+ * control Mulgara Transactions.
+ *
+ * @created 2007-11-07
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ *
+ * @copyright &copy;2006 <a href="http://www.topazproject.org/">Topaz Project</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public class MulgaraXAResourceContext {
+  private static final Logger logger =
+    Logger.getLogger(MulgaraXAResourceContext.class.getName());
+  /**
+   * Map from keyed from the {@link Integer} value of the various flags
+   * defined in {@link XAResource} and mapping to the formatted name for that
+   * flag.
+   */
+  private final static Map<Integer, String> flagMap = new HashMap<Integer, String>();
+
+  static {
+    flagMap.put(XAResource.TMENDRSCAN,   "TMENDRSCAN");
+    flagMap.put(XAResource.TMFAIL,       "TMFAIL");
+    flagMap.put(XAResource.TMJOIN,       "TMJOIN");
+    flagMap.put(XAResource.TMONEPHASE,   "TMONEPHASE");
+    flagMap.put(XAResource.TMRESUME,     "TMRESUME");
+    flagMap.put(XAResource.TMSTARTRSCAN, "TMSTARTRSCAN");
+    flagMap.put(XAResource.TMSUCCESS,    "TMSUCCESS");
+    flagMap.put(XAResource.TMSUSPEND,    "TMSUSPEND");
+  }
+
+  private final MulgaraExternalTransactionFactory factory;
+
+  protected final DatabaseSession session;
+
+  private final Assoc1toNMap<MulgaraExternalTransaction, Xid> xa2xid;
+
+  private final ReentrantLock mutex;
+
+  private final UUID uniqueId;
+
+  MulgaraXAResourceContext(MulgaraExternalTransactionFactory factory, DatabaseSession session) {
+    logger.info("Creating MulgaraXAResource");
+    this.factory = factory;
+    this.session = session;
+    this.xa2xid = new Assoc1toNMap<MulgaraExternalTransaction, Xid>();
+    this.mutex = new ReentrantLock();
+    this.uniqueId = UUID.randomUUID();
+  }
+
+  public XAResource getResource(boolean writing) {
+    return new MulgaraXAResource(writing);
+  }
+
+  private class MulgaraXAResource implements XAResource,
+      ResourceManagerInstanceAdaptor {
+    private final boolean writing;
+
+    public MulgaraXAResource(boolean writing) {
+      this.writing = writing;
+    }
+
+    /**
+     * Commit transaction identified by xid.
+     *
+     * Transaction must be Idle, Prepared, or Heuristically-Completed.
+     * If transaction not Heuristically-Completed we are required to finish it,
+     * clean up, and forget it.
+     * If transaction is Heuristically-Completed we throw an exception and wait
+     * for a call to forget().
+     */
+    public void commit(Xid xid, boolean onePhase) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing commit: " + parseXid(xid));
+        MulgaraExternalTransaction xa = xa2xid.get1(xid);
+        if (xa == null) {
+          throw new XAException(XAException.XAER_NOTA);
+        } else if (xa.isHeuristicallyRollbacked()) {
+          // HEURRB causes difficulties with JOTM - so throw the less precise
+          // but still correct RBROLLBACK.
+          // Note: Found the problem here - The J2EE Connector Architecture
+          // 7.6.2.2 requires an XA_RB* exception in the case of 1PC and 7.6.2.5
+          // implies that HEURRB is not permitted during 2PC - this seems broken
+          // to me, but that's the spec.
+//          throw new XAException(XAException.XA_HEURRB);
+          throw new XAException(XAException.XA_RBROLLBACK);
+        } else if (xa.isHeuristicallyCommitted()) {
+          throw new XAException(XAException.XA_HEURCOM);
+        }
+
+        if (onePhase) {
+          try {
+            xa.prepare(xid);
+          } catch (XAException ex) {
+            if (ex.errorCode != XAException.XA_RDONLY) {
+              doRollback(xa, xid);
+            }
+            // Note: XA spec requires us to forget about transactions that fail
+            // during commit.  doRollback throws exception under Heuristic
+            // Completion - when we do want to remember transaction.
+            xa2xid.remove1(xa);
+            throw ex;
+          }
+        }
+
+        try {
+          xa.commit(xid);
+          xa2xid.remove1(xa);
+        } catch (XAException ex) {
+          // We are not allowed to forget this transaction if we completed
+          // heuristically.
+          switch (ex.errorCode) { 
+            case XAException.XA_HEURHAZ:
+            case XAException.XA_HEURCOM:
+            case XAException.XA_HEURRB:
+            case XAException.XA_HEURMIX:
+              throw ex;
+            default:
+              xa2xid.remove1(xa);
+              throw ex;
+          }
+        }
+      } finally {
+        releaseMutex();
+      }
+    }
+
+    /**
+     * Deactivate a transaction.
+     *
+     * TMSUCCESS: Move to Idle and await call to rollback, prepare, or commit.
+     * TMFAIL: Move to RollbackOnly; await call to rollback.
+     * TMSUSPEND: Move to Idle and await start(TMRESUME) or end(TMSUCCESS|FAIL)
+     *
+     * In all cases disassociate from current session.
+     */
+    public void end(Xid xid, int flags) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing end(" + formatFlags(flags) + "): " + parseXid(xid));
+        MulgaraExternalTransaction xa = xa2xid.get1(xid);
+        if (xa == null) {
+          throw new XAException(XAException.XAER_NOTA);
+        }
+        switch (flags) {
+          case TMFAIL:
+            doRollback(xa, xid);
+            break;
+          case TMSUCCESS:
+            if (xa.isHeuristicallyRollbacked()) {
+              throw new XAException(XAException.XA_RBPROTO);
+            }
+            break;
+          case TMSUSPEND: // Should I be tracking the xid's state to ensure
+                          // conformance with the X/Open state diagrams?
+            break;
+          default:
+            logger.error("Invalid flag passed to end() : " + flags);
+            throw new XAException(XAException.XAER_INVAL);
+        }
+
+        try {
+          // If XA is currently associated with session, disassociate it.
+          factory.disassociateTransaction(session, xa);
+        } catch (MulgaraTransactionException em) {
+          logger.error("Error disassociating transaction from session", em);
+          throw new XAException(XAException.XAER_PROTO);
+        }
+      } finally {
+        releaseMutex();
+      }
+    }
+
+    public void forget(Xid xid) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing forget: " + parseXid(xid));
+        MulgaraExternalTransaction xa = xa2xid.get1(xid);
+        if (xa == null) {
+          throw new XAException(XAException.XAER_NOTA);
+        }
+        try {
+          if (!xa.isHeuristicallyRollbacked()) {
+            try {
+              xa.abortTransaction("External XA Manager specified 'forget'", new Throwable());
+            } catch (MulgaraTransactionException em) {
+              logger.error("Failed to abort transaction in forget", em);
+              throw new XAException(XAException.XAER_RMERR);
+            }
+          }
+        } finally {
+          xa2xid.remove1(xa);
+        }
+      } finally {
+        releaseMutex();
+      }
+    }
+
+    public int getTransactionTimeout() {
+      acquireMutex();
+      try {
+        logger.info("Performing getTransactionTimeout");
+        return 3600;
+      } finally {
+        releaseMutex();
+      }
+    }
+
+    public boolean isSameRM(XAResource xares) {
+      acquireMutex();
+      try {
+        logger.info("Performing isSameRM");
+        if (!xares.getClass().equals(MulgaraXAResource.class)) {
+          return false;
+        } else {
+          // Based on X/Open-XA-TP section 3.2 I believe a 'Resource Manager
+          // Instance' corresponds to a session, as each session 'supports
+          // independent transaction completion'.
+          return session == ((MulgaraXAResource)xares).getSession();
+        }
+      } finally {
+        releaseMutex();
+      }
+    }
+
+
+    public int prepare(Xid xid) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing prepare: " + parseXid(xid));
+        MulgaraExternalTransaction xa = xa2xid.get1(xid);
+        if (xa == null) {
+          throw new XAException(XAException.XAER_NOTA);
+        } else if (xa.isRollbacked()) {
+          throw new XAException(XAException.XA_RBROLLBACK);
+        }
+
+        xa.prepare(xid);
+
+        return XA_OK;
+      } finally {
+        releaseMutex();
+      }
+    }
+
+    /**
+     * We don't currently support recover.
+     * FIXME: We should at least handle the case where we are asked to recover
+     * when we haven't crashed.
+     */
+    public Xid[] recover(int flag) {
+      acquireMutex();
+      try {
+        logger.info("Performing recover");
+        return new Xid[] {};
+      } finally {
+        releaseMutex();
+      }
+    }
+
+
+    public void rollback(Xid xid) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing rollback: " + parseXid(xid));
+        MulgaraExternalTransaction xa = xa2xid.get1(xid);
+        if (xa == null) {
+          throw new XAException(XAException.XAER_NOTA);
+        }
+
+        doRollback(xa, xid);
+        // If we don't throw a Heuristic Exception we need to forget this
+        // transaction.  doRollback only throws Heuristic Exceptions.
+        xa2xid.remove1(xa);
+      } finally {
+        releaseMutex();
+      }
+    }
+
+
+    /**
+     * Performs rollback.  Only throws exception if transaction is subject to
+     * Heuristic Completion.
+     */
+    private void doRollback(MulgaraExternalTransaction xa, Xid xid) throws XAException {
+      if (xa.isHeuristicallyRollbacked()) {
+        logger.warn("Attempted to rollback heuristically rollbacked transaction: " + xa.getHeuristicCode());
+        throw new XAException(xa.getHeuristicCode());
+      } else if (!xa.isRollbacked()) {
+        xa.rollback(xid);
+      }
+    }
+
+
+    public boolean setTransactionTimeout(int seconds) {
+      acquireMutex();
+      try {
+        logger.info("Performing setTransactionTimeout");
+        return false;
+      } finally {
+        releaseMutex();
+      }
+    }
+
+
+    public void start(Xid xid, int flags) throws XAException {
+      acquireMutex();
+      try {
+        xid = convertXid(xid);
+        logger.info("Performing start(" + formatFlags(flags) + "): " + parseXid(xid));
+        switch (flags) {
+          case TMNOFLAGS:
+            if (xa2xid.containsN(xid)) {
+              throw new XAException(XAException.XAER_DUPID);
+            } else if (factory.hasAssociatedTransaction(session)) {
+              throw new XAException(XAException.XA_RBDEADLOCK);
+            } else {
+              // FIXME: Need to consider read-only transactions here.
+              try {
+                MulgaraExternalTransaction xa = factory.createTransaction(session, xid, writing);
+                xa2xid.put(xa, xid);
+              } catch (MulgaraTransactionException em) {
+                logger.error("Failed to create transaction", em);
+                throw new XAException(XAException.XAER_RMFAIL);
+              }
+            }
+            break;
+          case TMJOIN:
+            if (!factory.hasAssociatedTransaction(session)) {
+              throw new XAException(XAException.XAER_NOTA);
+            } else if (!factory.getAssociatedTransaction(session).getXid().equals(xid)) {
+              throw new XAException(XAException.XAER_OUTSIDE);
+            }
+            break;
+          case TMRESUME:
+            MulgaraExternalTransaction xa = xa2xid.get1(xid);
+            if (xa == null) {
+              throw new XAException(XAException.XAER_NOTA);
+            } else if (xa.isRollbacked()) {
+              throw new XAException(XAException.XA_RBROLLBACK);
+            } else {
+              if (!factory.associateTransaction(session, xa)) {
+                // session already associated with a transaction.
+                throw new XAException(XAException.XAER_PROTO);
+              }
+            }
+            break;
+        }
+      } finally {
+        releaseMutex();
+      }
+
+    }
+
+    public Serializable getRMId() {
+      return uniqueId;
+    }
+
+    /**
+     * Required only because Java has trouble with accessing fields from
+     * inner-classes.
+     */
+    private DatabaseSession getSession() { return session; }
+  }
+  
+  /**
+   * Used to replace the built in monitor to allow it to be properly released
+   * during potentially blocking operations.  All potentially blocking
+   * operations involve writes, so in these cases the write-lock is reserved
+   * allowing the mutex to be safely released and then reobtained after the
+   * blocking operation concludes.
+   */
+  protected void acquireMutex() {
+    mutex.lock();
+  }
+
+
+  protected void releaseMutex() {
+    if (!mutex.isHeldByCurrentThread()) {
+      throw new IllegalStateException("Attempt to release mutex without holding mutex");
+    }
+
+    mutex.unlock();
+  }
+
+  public static String parseXid(Xid xid) {
+    return xid.toString();
+  }
+
+  private static InternalXid convertXid(Xid xid) {
+    return new InternalXid(xid);
+  }
+
+  /**
+   * Provides an Xid that compares equal by value.
+   */
+  private static class InternalXid implements Xid {
+    private byte[] bq;
+    private int fi;
+    private byte[] gtid;
+
+    public InternalXid(Xid xid) {
+      byte[] tbq = xid.getBranchQualifier();
+      byte[] tgtid = xid.getGlobalTransactionId();
+      this.bq = new byte[tbq.length];
+      this.fi = xid.getFormatId();
+      this.gtid = new byte[tgtid.length];
+      System.arraycopy(tbq, 0, this.bq, 0, tbq.length);
+      System.arraycopy(tgtid, 0, this.gtid, 0, tgtid.length);
+    }
+
+    public byte[] getBranchQualifier() {
+      return bq;
+    }
+
+    public int getFormatId() {
+      return fi;
+    }
+
+    public byte[] getGlobalTransactionId() {
+      return gtid;
+    }
+
+    public int hashCode() {
+      return Arrays.hashCode(bq) ^ fi ^ Arrays.hashCode(gtid);
+    }
+
+    public boolean equals(Object rhs) {
+      if (!(rhs instanceof InternalXid)) {
+        return false;
+      } else {
+        InternalXid rhx = (InternalXid)rhs;
+        return this.fi == rhx.fi &&
+            Arrays.equals(this.bq, rhx.bq) &&
+            Arrays.equals(this.gtid, rhx.gtid);
+      }
+    }
+
+    public String toString() {
+      return ":" + fi + ":" + Arrays.hashCode(gtid) + ":" + Arrays.hashCode(bq) + ":";
+    }
+  }
+
+  /**
+   * Format bitmasks defined by {@link XAResource}.
+   *
+   * @param flags  a bitmask composed from the constants defined in
+   *   {@link XAResource}
+   * @return a formatted representation of the <var>flags</var>
+   */
+  private static String formatFlags(int flags)
+  {
+    // Short-circuit evaluation if we've been explicitly passed no flags
+    if (flags == XAResource.TMNOFLAGS) {
+      return "TMNOFLAGS";
+    }
+
+    StringBuffer buffer = new StringBuffer();
+
+    // Add any flags that are present
+    for (Map.Entry<Integer, String> entry : flagMap.entrySet()) {
+      int flag = entry.getKey();
+
+      // If this flag is present, add it to the formatted output and remove
+      // from the bitmask
+      if ((flag & flags) == flag) {
+        if (buffer.length() > 0) {
+          buffer.append("|");
+        }
+        buffer.append(entry.getValue());
+        flags &= ~flag;
+      }
+    }
+
+    // We would expect to have removed all flags by this point
+    // If there's some unknown flag we've missed, format it as hexadecimal
+    if (flags != 0) {
+      if (buffer.length() > 0) {
+        buffer.append(",");
+      }
+      buffer.append("0x").append(Integer.toHexString(flags));
+    }
+
+    return buffer.toString();
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/Operation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/Operation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/Operation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -54,13 +54,11 @@
    * Perform a transactional operation.
    *
    * @param systemResolver
-   * @param resolverSessionFactory
    * @param metadata
    * @throws Exception if the operation cannot be completed
    */
   public void execute(OperationContext         operationContext,
                       SystemResolver           systemResolver,
-                      ResolverSessionFactory   resolverSessionFactory,
                       DatabaseMetadata         metadata) throws Exception;
 
   /**

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/OperationContext.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/OperationContext.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/OperationContext.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -52,8 +52,8 @@
  *   Technology, Inc</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-interface OperationContext
-{
+public interface OperationContext {
+
   /**
    * Find a {@link ResolverFactory} capable of generating a {#link Resolver} to
    * manipulate a specified model.

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PersistentResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PersistentResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PersistentResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -144,7 +144,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
-
     return resolverSession.getSPObjectFactory();
   }
+
+  public SPObject findSPObject(long gNode) throws StringPoolException {
+    return resolverSession.findSPObject(gNode);
+  }
+
+  public long findGNode(SPObject spObject) throws StringPoolException {
+    return resolverSession.findGNode(spObject);
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PreallocateOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PreallocateOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/PreallocateOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -87,7 +87,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception {
 
     this.localNode = systemResolver.localizePersistent(node);

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/QueryOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/QueryOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/QueryOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -132,7 +132,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     if (query != null) {

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RemoveModelOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RemoveModelOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RemoveModelOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -121,7 +121,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     long model = systemResolver.localize(new URIReferenceImpl(modelURI));

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RestoreOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RestoreOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/RestoreOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -53,11 +53,9 @@
 // Local packages
 import org.mulgara.query.*;
 import org.mulgara.resolver.spi.*;
-import org.mulgara.store.nodepool.NodePool;
 import org.mulgara.store.statement.StatementStore;
 import org.mulgara.store.stringpool.SPObject;
 import org.mulgara.store.stringpool.SPObjectFactory;
-import org.mulgara.store.stringpool.StringPool;
 import org.mulgara.store.tuples.Tuples;
 import org.mulgara.util.IntFile;
 import org.mulgara.util.TempDir;
@@ -123,7 +121,6 @@
 
   public void execute(OperationContext         operationContext,
                       SystemResolver           systemResolver,
-                      ResolverSessionFactory   resolverSessionFactory,
                       DatabaseMetadata         metadata) throws Exception
   {
     InputStream is = inputStream;
@@ -142,7 +139,7 @@
           "UTF-8"
       ));
 
-      restoreDatabase(systemResolver, resolverSessionFactory, metadata, br);
+      restoreDatabase(systemResolver, systemResolver, metadata, br);
     } finally {
       if (br != null) {
         // Close the BufferedReader if it exists.  This will also close the
@@ -160,12 +157,11 @@
    * Restore the entire database.
    *
    * @param resolver Resolver
-   * @param resolverSessionFactory ResolverSessionFactory
    * @param metadata DatabaseMetadata
    * @param br BufferedReader
    */
   private void restoreDatabase(
-      Resolver resolver, ResolverSessionFactory resolverSessionFactory,
+      Resolver resolver, ResolverSession resolverSession,
       DatabaseMetadata metadata, BufferedReader br
   ) throws Exception {
     // Check the header of the backup file.
@@ -177,9 +173,9 @@
 
     if (versionString.equals(BACKUP_VERSION)) {
       assert BACKUP_VERSION.equals("6");
-      restoreDatabaseV6(resolver, resolverSessionFactory, metadata, br);
+      restoreDatabaseV6(resolver, resolverSession, metadata, br);
     } else if (versionString.equals("4")) {
-      restoreDatabaseV4(resolver, resolverSessionFactory, metadata, br);
+      restoreDatabaseV4(resolver, resolverSession, metadata, br);
     } else {
       throw new QueryException(
           "Unsupported backup file version: V" + versionString
@@ -197,12 +193,12 @@
    * Restore the entire database from a V4 backup file.
    *
    * @param resolver Resolver
-   * @param resolverSessionFactory ResolverSessionFactory
+   * @param resolverSession resolverSession
    * @param metadata DatabaseMetadata
    * @param br BufferedReader
    */
   private void restoreDatabaseV4(
-      Resolver resolver, ResolverSessionFactory resolverSessionFactory,
+      Resolver resolver, ResolverSession resolverSession,
       DatabaseMetadata metadata, BufferedReader br
   ) throws Exception {
     if (logger.isInfoEnabled()) {
@@ -263,14 +259,12 @@
     try {
       n2nMap = IntFile.open(n2nFile);
 
-      StringPool stringPool = resolverSessionFactory.getPersistentStringPool();
-      SPObjectFactory spof = stringPool.getSPObjectFactory();
-      NodePool nodePool = resolverSessionFactory.getPersistentNodePool();
+      SPObjectFactory spof = resolverSession.getSPObjectFactory();
 
       // Nodes in the backup file's coordinate space.
-      long systemModelNode = NodePool.NONE;
-      long emptyGroupNode = NodePool.NONE;
-      long tksIntModelNode = NodePool.NONE;
+      long systemModelNode = BackupRestoreSession.NONE;
+      long emptyGroupNode = BackupRestoreSession.NONE;
+      long tksIntModelNode = BackupRestoreSession.NONE;
 
       // Load the strings.
       while (((line = br.readLine()) != null) && !line.equals("TRIPLES")) {
@@ -304,7 +298,7 @@
         // If the SPObject is already in the string pool then use the
         // existing node ID, otherwise allocate a new node and put the
         // SPObject into the string pool.
-        long newGNode = stringPool.findGNode(spObject, nodePool);
+        long newGNode = resolverSession.findGNode(spObject);
 
         n2nMap.putLong(gNode, newGNode);
       }
@@ -318,19 +312,19 @@
 
       // Check that the systemModel, emptyGroup and tksIntModel nodes were
       // found.
-      if (systemModelNode == NodePool.NONE) {
+      if (systemModelNode == BackupRestoreSession.NONE) {
         throw new QueryException(
             "The system model node \"<#>\" was not found in the RDFNODES " +
             "section of the backup file: " + sourceURI
         );
       }
-      if (emptyGroupNode == NodePool.NONE) {
+      if (emptyGroupNode == BackupRestoreSession.NONE) {
         throw new QueryException(
             "The node for EMPTY_GROUP was not found in the RDFNODES " +
             "section of the backup file: " + sourceURI
         );
       }
-      if (tksIntModelNode == NodePool.NONE) {
+      if (tksIntModelNode == BackupRestoreSession.NONE) {
         throw new QueryException(
             "The node for \"" + TKS_INT_MODEL_URI +
             "\" was not found in the RDFNODES section of the backup file: " +
@@ -393,12 +387,12 @@
             Long groupL = new Long(node0);
             Set modelSet = (Set)g2mMap.get(groupL);
             if (modelSet == null) {
-              assert n2nMap.getLong(node0) == NodePool.NONE;
+              assert n2nMap.getLong(node0) == BackupRestoreSession.NONE;
               modelSet = new HashSet();
               g2mMap.put(groupL, modelSet);
             }
-            assert n2nMap.getLong(node2) != NodePool.NONE;
-            modelSet.add(new Long(getNode(n2nMap, node2, nodePool)));
+            assert n2nMap.getLong(node2) != BackupRestoreSession.NONE;
+            modelSet.add(new Long(getNode(n2nMap, node2, resolverSession)));
 
             // Mark this node as a group.  This indicates that a lookup must
             // be performed on g2mMap.
@@ -461,11 +455,11 @@
             }
           } while (buffer.hasRemaining());
         }
-        long node0 = getNode(n2nMap, tripleBuffer.get(), nodePool);
-        long node1 = getNode(n2nMap, tripleBuffer.get(), nodePool);
-        long node2 = getNode(n2nMap, tripleBuffer.get(), nodePool);
+        long node0 = getNode(n2nMap, tripleBuffer.get(), resolverSession);
+        long node1 = getNode(n2nMap, tripleBuffer.get(), resolverSession);
+        long node2 = getNode(n2nMap, tripleBuffer.get(), resolverSession);
         long meta = tripleBuffer.get();
-        long node3 = getNode(n2nMap, meta, nodePool);
+        long node3 = getNode(n2nMap, meta, resolverSession);
 
         // TODO Write a class that implements Statements to restore the
         // entire TRIPLES section with one call to modifyModel().
@@ -519,12 +513,12 @@
    * Restore the entire database from a V6 backup file.
    *
    * @param resolver Resolver
-   * @param resolverSessionFactory ResolverSessionFactory
+   * @param resolverSession resolverSession
    * @param metadata DatabaseMetadata
    * @param br BufferedReader
    */
   private void restoreDatabaseV6(
-      Resolver resolver, ResolverSessionFactory resolverSessionFactory,
+      Resolver resolver, ResolverSession resolverSession,
       DatabaseMetadata metadata, BufferedReader br
   ) throws Exception {
     if (logger.isInfoEnabled()) {
@@ -582,9 +576,7 @@
     try {
       n2nMap = IntFile.open(n2nFile);
 
-      StringPool stringPool = resolverSessionFactory.getPersistentStringPool();
-      SPObjectFactory spof = stringPool.getSPObjectFactory();
-      NodePool nodePool = resolverSessionFactory.getPersistentNodePool();
+      SPObjectFactory spof = resolverSession.getSPObjectFactory();
 
       // Load the strings.
       while (((line = br.readLine()) != null) && !line.equals("TRIPLES")) {
@@ -597,7 +589,7 @@
         // If the SPObject is already in the string pool then use the
         // existing node ID, otherwise allocate a new node and put the
         // SPObject into the string pool.
-        long newGNode = stringPool.findGNode(spObject, nodePool);
+        long newGNode = resolverSession.findGNode(spObject);
 
         n2nMap.putLong(gNode, newGNode);
       }
@@ -646,10 +638,10 @@
         // TODO Write a class that implements Statements to restore the
         // entire TRIPLES section with one call to modifyModel().
         resolver.modifyModel(
-          getNode(n2nMap, node3, nodePool),
-          new SingletonStatements(getNode(n2nMap, node0, nodePool),
-                                  getNode(n2nMap, node1, nodePool),
-                                  getNode(n2nMap, node2, nodePool)),
+          getNode(n2nMap, node3, resolverSession),
+          new SingletonStatements(getNode(n2nMap, node0, resolverSession),
+                                  getNode(n2nMap, node1, resolverSession),
+                                  getNode(n2nMap, node2, resolverSession)),
           DatabaseSession.ASSERT_STATEMENTS
         );
       }
@@ -673,19 +665,17 @@
    * @param n2nMap the IntFile that maps from backup file node IDs to current
    *      store node IDs.
    * @param oldNode the backup file node ID.
-   * @param nodePool the NodePool to allocate blank nodes from.
+   * @param ResolverSession Used to allocate new nodes.
    * @return the new node ID that the specified backup file node ID maps to.
    * @throws Exception EXCEPTION TO DO
    */
-  private static long getNode(
-      IntFile n2nMap, long oldNode, NodePool nodePool
-  ) throws Exception {
+  private static long getNode(IntFile n2nMap, long oldNode, ResolverSession resolverSession) throws Exception {
     long newNode = n2nMap.getLong(oldNode);
 
     // IntFile.getLong() returns zero for entries that have never been
     // written to.
     if (newNode == 0) {
-      newNode = nodePool.newNode();
+      newNode = resolverSession.newBlankNode();
       n2nMap.putLong(oldNode, newNode);
     }
 

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/SetModelOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/SetModelOperation.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/SetModelOperation.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -133,7 +133,6 @@
 
   public void execute(OperationContext       operationContext,
                       SystemResolver         systemResolver,
-                      ResolverSessionFactory resolverSessionFactory,
                       DatabaseMetadata       metadata) throws Exception
   {
     // A prior call to execute will have set statementCount >= 0.

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/StringPoolSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/StringPoolSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/StringPoolSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,13 +31,7 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.*;
-import javax.transaction.xa.XAResource;
 
-// Java 2 enterprise packages
-import javax.transaction.RollbackException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
 // Third party packages
 import org.apache.log4j.Logger;
 import org.jrdf.graph.*;
@@ -46,7 +40,6 @@
 import org.mulgara.query.*;
 import org.mulgara.query.rdf.*;
 import org.mulgara.resolver.spi.*;
-import org.mulgara.server.SessionFactory;
 import org.mulgara.store.nodepool.NodePool;
 import org.mulgara.store.nodepool.NodePoolException;
 import org.mulgara.store.stringpool.SPObject;
@@ -74,7 +67,7 @@
  *   Technology, Inc</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-public class StringPoolSession implements XAResolverSession
+public class StringPoolSession implements XAResolverSession, BackupRestoreSession
 {
   /** Logger.  */
   private static final Logger logger =
@@ -86,13 +79,6 @@
    */
   private static final long NONE = NodePool.NONE;
 
-  /**
-   * Whether transactionality is enabled.
-   *
-   * Disabling transactionality can be useful for debugging.
-   */
-  private static final boolean TRANSACTIONAL = true;
-
   private static final int OBTAIN   = 0;
   private static final int PREPARE  = 1;
   private static final int COMMIT   = 2;
@@ -116,7 +102,7 @@
   private final URI databaseURI;
 
   /** The set of alternative hostnames for the current host. */
-  private final Set hostnameAliases;
+  private final Set<String> hostnameAliases;
 
   /** Where to store literals for this phase.  */
   private XAStringPool persistentStringPool;
@@ -130,9 +116,6 @@
   /** Where to store literals which won't outlive this session.  */
   private final StringPool temporaryStringPool;
   
-  /** Maps blank nodes into remembered IDs. */
-  Map<BlankNode,Long> blankNodeCache = new HashMap<BlankNode,Long>();
-
   private int state;
 
   private SimpleXAResource[] resources;
@@ -140,13 +123,14 @@
   private Object globalLock;
 
   StringPoolSession(URI          databaseURI,
-                    Set          hostnameAliases,
+                    Set<String>  hostnameAliases,
                     XAStringPool persistentStringPool,
                     XANodePool   persistentNodePool,
                     StringPool   temporaryStringPool,
                     NodePool     temporaryNodePool,
-                    Object globalLock)
-  {
+                    Object globalLock
+  ) {
+
     if (logger.isDebugEnabled()) {
       logger.debug("Constructing StringPoolSession " + System.identityHashCode(this), new Throwable());
     }
@@ -168,8 +152,8 @@
   // Globalize/Localize methods.
   //
 
-  public Node globalize(long localNode) throws GlobalizeException
-  {
+  public Node globalize(long localNode) throws GlobalizeException {
+
     if (state == ROLLBACK || state == RELEASE) {
       throw new GlobalizeException(localNode, "Attempting to globalize outside transaction.");
     }
@@ -200,23 +184,19 @@
   }
 
 
-  public long lookup(Node node) throws LocalizeException
-  {
+  public long lookup(Node node) throws LocalizeException {
     return localize(node, READ | TEMP);
   }
 
-  public long lookupPersistent(Node node) throws LocalizeException
-  {
+  public long lookupPersistent(Node node) throws LocalizeException {
     return localize(node, READ | PERSIST);
   }
 
-  public long localize(Node node) throws LocalizeException
-  {
+  public long localize(Node node) throws LocalizeException {
     return localize(node, WRITE | TEMP);
   }
 
-  public long localizePersistent(Node node) throws LocalizeException
-  {
+  public long localizePersistent(Node node) throws LocalizeException {
     return localize(node, WRITE | PERSIST);
   }
 
@@ -233,7 +213,6 @@
     synchronized (this.globalLock) {
       this.persistentStringPool.refresh();
       this.persistentNodePool.refresh();
-      blankNodeCache.clear();
       // !!Review: Call rollback on temporary? NB. Can't rollback non XA-SP/NP.
       //this.temporaryStringPool.refresh();
       //this.temporaryNodePool.refresh();
@@ -245,8 +224,7 @@
   }
 
 
-  public void prepare() throws SimpleXAResourceException
-  {
+  public void prepare() throws SimpleXAResourceException {
     if (logger.isDebugEnabled()) {
       logger.debug("Preparing phase on StringPoolSession " + System.identityHashCode(this) + " SP=" + System.identityHashCode(persistentStringPool));
     }
@@ -266,8 +244,7 @@
   }
 
 
-  public void commit() throws SimpleXAResourceException
-  {
+  public void commit() throws SimpleXAResourceException {
     if (logger.isDebugEnabled()) {
       logger.debug("Committing phase on StringPoolSession " + System.identityHashCode(this));
     }
@@ -282,7 +259,6 @@
     synchronized (globalLock) {
       persistentStringPool.commit();
       persistentNodePool.commit();
-      blankNodeCache.clear();
       for (int i = 0; i < resources.length; i++) {
         resources[i].commit();
       }
@@ -290,8 +266,7 @@
   }
 
 
-  public void rollback() throws SimpleXAResourceException
-  {
+  public void rollback() throws SimpleXAResourceException {
     if (logger.isDebugEnabled()) {
       logger.debug("Rollback phase on StringPoolSession " + System.identityHashCode(this));
     }
@@ -301,15 +276,13 @@
     state = ROLLBACK;
     persistentStringPool.rollback();
     persistentNodePool.rollback();
-    blankNodeCache.clear();
     for (int i = 0; i < resources.length; i++) {
       resources[i].rollback();
     }
   }
 
 
-  public void release() throws SimpleXAResourceException
-  {
+  public void release() throws SimpleXAResourceException {
     if (logger.isDebugEnabled()) {
       logger.debug("Release phase on StringPoolSession " + System.identityHashCode(this));
     }
@@ -323,7 +296,6 @@
 
     persistentStringPool.release();
     persistentNodePool.release();
-    blankNodeCache.clear();
 
     // TODO determine if release() should be called for the temp components.
     //temporaryStringPool.release();
@@ -437,9 +409,7 @@
     try {
       spObject = spoFactory.newSPObject(node);
     } catch (RuntimeException ex) {
-      throw new LocalizeException(
-          node, "Couldn't convert Node to SPObject", ex
-      );
+      throw new LocalizeException(node, "Couldn't convert Node to SPObject", ex);
     }
     assert spObject != null;
 
@@ -453,8 +423,7 @@
   }
 
 
-  protected long localizeBlankNode(BlankNode node, int flags)
-      throws LocalizeException {
+  protected long localizeBlankNode(BlankNode node, int flags) throws LocalizeException {
     try {
 
       // Check to see that it's a blank node impl (a Mulgara blank node)
@@ -464,15 +433,12 @@
         // If the blank node id is greater then zero return it.
         // FIXME: we should be checking that the BlankNodeImpl came from the
         //        correct phase, otherwise it is invalid to extract the NodeId.
-        if (bi.getNodeId() > 0) {
-          return bi.getNodeId();
-        }
+        if (bi.getNodeId() > 0) return bi.getNodeId();
 
         // If the blank node does not have a blank node id and we are in a read
         // phase then throw an exception.
         if ((bi.getNodeId() == 0) && ((flags & WRITE_MASK) == READ)) {
-          throw new LocalizeException(node, "Attempt to get a node ID from " +
-              "a non-allocated BlankNodeImpl in a read phase");
+          throw new LocalizeException(node, "Attempt to get a node ID from a non-allocated BlankNodeImpl in a read phase");
         }
 
         // If we are in a write phase.
@@ -485,8 +451,7 @@
           } else if (bi.getNodeId() == 0) {
             if ((flags & STORE_MASK) == TEMP) {
               bi.setNodeId(-temporaryNodePool.newNode());
-            }
-            else {
+            } else {
               bi.setNodeId(persistentNodePool.newNode());
             }
           }
@@ -494,13 +459,11 @@
         }
         // Throw an exception here if we're in a read phase and the blank node
         // id is negative.
-        throw new LocalizeException(node, "Attempt to persist a local blank " +
-           "node in a read phase");
+        throw new LocalizeException(node, "Attempt to persist a local blank node in a read phase");
       } else if ((flags & WRITE_MASK) == WRITE) {
       // Some other implementation of BlankNode, so we can't access internal
       // node ID and we can only create one - we must be in the WRITE phase.
         return getAllocatedNodeId(node, flags);
-
       } else {
         // If it's a read phase and not the local BlankNode then throw an
         // exception.
@@ -520,7 +483,6 @@
    */
   protected long getAllocatedNodeId(BlankNode bn, int flags) throws NodePoolException {
     assert !(bn instanceof BlankNodeImpl);
-    if (blankNodeCache.containsKey(bn)) return blankNodeCache.get(bn);
 
     long nodeId;
     if ((flags & STORE_MASK) == TEMP) {
@@ -528,28 +490,17 @@
     } else {
       nodeId = persistentNodePool.newNode();
     }
-    blankNodeCache.put(bn, nodeId);
     return nodeId;
   }
 
-  protected Node globalizeBlankNode(long localNode, SPObject spObject) throws
-      GlobalizeException {
+  protected Node globalizeBlankNode(long localNode, SPObject spObject) throws GlobalizeException {
 
-    Node node = null;
-
-    if (spObject == null) {
-      node = new BlankNodeImpl(localNode);
-    } else {
-      node = spObject.getRDFNode();
-    }
-
-    return node;
+    return (spObject == null) ? new BlankNodeImpl(localNode) : spObject.getRDFNode();
   }
 
 
-  private long localizeSPObject(SPObject spObject, int flags)
-      throws StringPoolException, NodePoolException
-  {
+  private long localizeSPObject(SPObject spObject, int flags) throws StringPoolException, NodePoolException {
+
     boolean persistent = true;
     SPObject relativeSPObject = mapRelative(spObject);
     long localNode = persistentStringPool.findGNode(relativeSPObject);
@@ -630,9 +581,7 @@
           String query = uri.getQuery();
           String ssp = databaseURI.getSchemeSpecificPart();
           if (query != null) ssp += '?' + query;
-          spObject = spObjectFactory.newSPURI(new URI(
-              databaseURI.getScheme(), ssp, uri.getFragment()
-          ));
+          spObject = spObjectFactory.newSPURI(new URI(databaseURI.getScheme(), ssp, uri.getFragment()));
         } catch (URISyntaxException ex) {
           logger.warn(
               "Cannot create absolute URI with base:\"" + databaseURI +
@@ -659,10 +608,7 @@
       String scheme = uri.getScheme();
       String fragment = uri.getFragment();
 
-      if (
-          scheme != null && scheme.equals(databaseURI.getScheme()) &&
-          fragment != null
-      ) {
+      if (scheme != null && scheme.equals(databaseURI.getScheme()) && fragment != null ) {
         if (databaseURI.isOpaque()) {
           // databaseURI is opaque.
           if (uri.isOpaque()) {
@@ -681,17 +627,11 @@
             if (ssp.equals(databaseURI.getSchemeSpecificPart())) {
               // Construct a new relative uri with just the fragment and
               // optional query string.
-              SPObjectFactory spObjectFactory =
-                  persistentStringPool.getSPObjectFactory();
+              SPObjectFactory spObjectFactory = persistentStringPool.getSPObjectFactory();
               try {
-                spObject = spObjectFactory.newSPURI(new URI(
-                    null, null, null, query, fragment
-                ));
+                spObject = spObjectFactory.newSPURI(new URI(null, null, null, query, fragment));
               } catch (URISyntaxException ex) {
-                logger.warn(
-                    "Cannot create relative URI with fragment:\"" + fragment +
-                    "\"", ex
-                );
+                logger.warn("Cannot create relative URI with fragment:\"" + fragment + "\"", ex);
               }
             }
           }
@@ -715,17 +655,11 @@
           ) {
             // Construct a new relative uri with just the fragment and
             // optional query string.
-            SPObjectFactory spObjectFactory =
-                persistentStringPool.getSPObjectFactory();
+            SPObjectFactory spObjectFactory = persistentStringPool.getSPObjectFactory();
             try {
-              spObject = spObjectFactory.newSPURI(new URI(
-                  null, null, null, uri.getQuery(), fragment
-              ));
+              spObject = spObjectFactory.newSPURI(new URI(null, null, null, uri.getQuery(), fragment));
             } catch (URISyntaxException ex) {
-              logger.warn(
-                  "Cannot create relative URI with fragment:\"" + fragment +
-                  "\"", ex
-              );
+              logger.warn("Cannot create relative URI with fragment:\"" + fragment + "\"", ex);
             }
           }
         }
@@ -773,4 +707,20 @@
     return result;
   }
 
+  /**
+   * {@inheritDoc}
+   *
+   * NB: This method does not perform any absolute/relative URI mapping.
+   */
+  public SPObject findSPObject(long gNode) throws StringPoolException {
+    if (gNode < NodePool.MIN_NODE) {
+      throw new IllegalArgumentException("Attempt to resolve temporary gNode in BackupRestoreSession");
+    }
+
+    return persistentStringPool.findSPObject(gNode);
+  }
+
+  public long findGNode(SPObject spObject) throws StringPoolException {
+    return persistentStringPool.findGNode(spObject, persistentNodePool);
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -167,8 +167,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
 
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/XADatabaseSessionUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/XADatabaseSessionUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver/java/org/mulgara/resolver/XADatabaseSessionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -611,7 +611,7 @@
 
         // Evaluate the query
         Answer answer = new ArrayAnswer(session.query(new Query(
-          (List<Object>)(List)test.selectList,          // SELECT
+          test.selectList,          // SELECT
           test.model,               // FROM
           test.query,               // WHERE
           null,                     // HAVING

Modified: branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/ForeignBlankNode.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/ForeignBlankNode.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/ForeignBlankNode.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -49,7 +49,7 @@
    * @return A string containing all the unique features of the node.
    */
   public String toString() {
-    return serverUri.toString() + ":_" + nodeId;
+    return "_:" + serverUri.toString() + ":" + nodeId;
   }
 
 
@@ -75,7 +75,7 @@
    * @return Hashcode of the nodeid.
    */
   public int hashCode() {
-    return serverHashCode ^ (int)(nodeId ^ (nodeId >>>32));
+    return serverHashCode ^ (int)(nodeId ^ (nodeId >>> 32));
   }
 
 }

Modified: branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/NetworkDelegator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/NetworkDelegator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-distributed/java/org/mulgara/resolver/distributed/NetworkDelegator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -198,7 +198,7 @@
     );
 
     // convert the variable set to a variable list - add types via unchecked casts
-    List<Object> variables = new ArrayList<Object>((Set<Variable>)globalConstraint.getVariables());
+    List<Variable> variables = new ArrayList<Variable>((Set<Variable>)globalConstraint.getVariables());
     // build the new query
     return new Query(variables, new ModelResource(model.getURI()), globalConstraint, null, Collections.EMPTY_LIST, null, 0, new UnconstrainedAnswer());
   }

Modified: branches/mgr-61-sparql/src/jar/resolver-filesystem/java/org/mulgara/resolver/filesystem/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-filesystem/java/org/mulgara/resolver/filesystem/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-filesystem/java/org/mulgara/resolver/filesystem/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -165,7 +165,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 
+  public SPObject findSPObject(long gNode) {
     throw new UnsupportedOperationException("Not Implemented on test class");
   }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver-http/java/org/mulgara/resolver/http/HttpContentUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-http/java/org/mulgara/resolver/http/HttpContentUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-http/java/org/mulgara/resolver/http/HttpContentUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -233,7 +233,7 @@
     content = new HttpContent(new URL("http://purl.org/dc/elements/1.1"));
     stream = content.newInputStream();
     assertTrue("Expecting an input stream ", stream != null);
-    assertTrue("Expecting 14054 bytes from inputstream ", dumpAndCheck(stream) == 14054);
+    assertEquals("Expecting 14054 bytes from inputstream ", 17564, dumpAndCheck(stream));
     stream.close();
     
   }

Modified: branches/mgr-61-sparql/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -37,7 +37,7 @@
 import java.util.Map;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.search.Hits;
 
@@ -79,8 +79,7 @@
     Cloneable {
 
   /** Logger.  */
-  private final static Category logger =
-      Category.getInstance(FullTextStringIndexTuples.class.getName());
+  private final static Logger logger = Logger.getLogger(FullTextStringIndexTuples.class);
 
   /** Description of the Field */
   private final static String SCORE_COLUMN = "score";

Modified: branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *    Migration to AbstractXAResource copyright 2008 The Topaz Foundation
  *
  * [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
@@ -84,8 +85,10 @@
    */
   private final Set<Stating> statingSet;
 
-  private XAResolverSession xaResolverSession;
+  private final XAResource xares;
 
+  private final XAResolverSession xaResolverSession;
+
   //
   // Constructors
   //
@@ -105,34 +108,30 @@
    *   is {@link NodePool#NONE}
    */
   MemoryResolver(ResolverSession resolverSession,
-                 Resolver        systemResolver,
                  long            rdfType,
-                 long            systemModel,
                  URI             modelTypeURI,
                  Set<Stating>    statingSet)
       throws ResolverFactoryException {
-
-    // Validate "modelType" parameter
-    if (modelTypeURI == null) {
-      throw new IllegalArgumentException("Model type can't be null");
-    }
-
-    // Initialize fields
-    memoryModelTypeURI = modelTypeURI;
-    this.rdfType = rdfType;
-    this.resolverSession = resolverSession;
-    this.statingSet = statingSet;
-    this.xaResolverSession = null;
+    this(resolverSession, rdfType, modelTypeURI, statingSet, null, null);
   }
 
-
   MemoryResolver(long              rdfType,
-                 long              systemModel,
                  URI               modelTypeURI,
                  Set<Stating>      statingSet,
-                 XAResolverSession resolverSession)
+                 XAResolverSession resolverSession,
+                 ResolverFactory   resolverFactory)
       throws ResolverFactoryException {
-    
+    this(resolverSession, rdfType, modelTypeURI, statingSet, resolverSession,
+         resolverFactory);
+  }
+
+  private MemoryResolver(ResolverSession   resolverSession,
+                         long              rdfType,
+                         URI               modelTypeURI,
+                         Set<Stating>      statingSet,
+                         XAResolverSession xaResolverSession,
+                         ResolverFactory   resolverFactory)
+      throws ResolverFactoryException {
     // Validate "modelType" parameter
     if (modelTypeURI == null) {
       throw new IllegalArgumentException("Model type can't be null");
@@ -143,20 +142,21 @@
     this.rdfType = rdfType;
     this.resolverSession = resolverSession;
     this.statingSet = statingSet;
-    this.xaResolverSession = resolverSession;
+    this.xaResolverSession = xaResolverSession;
+
+    this.xares = (xaResolverSession != null) ?
+          new MemoryXAResource(10, xaResolverSession, resolverFactory) :
+          new DummyXAResource(10);
   }
 
 
+
   //
   // Methods implementing Resolver
   //
 
   public XAResource getXAResource() {
-    if (xaResolverSession != null) {
-      return new MemoryXAResource(10, xaResolverSession);
-    } else {
-      return new DummyXAResource(10);
-    }
+    return xares;
   }
 
 
@@ -330,10 +330,17 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
-
     return resolverSession.getSPObjectFactory();
   }
 
+  public SPObject findSPObject(long gNode) throws StringPoolException {
+    return resolverSession.findSPObject(gNode);
+  }
+
+  public long findGNode(SPObject spObject) throws StringPoolException {
+    return resolverSession.findGNode(spObject);
+  }
+
   //
   // Internal methods
   //

Modified: branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -74,11 +74,6 @@
 
 
   /**
-   * The preallocated local node representing the system model (<code>#</code>).
-   */
-  private long systemModel;
-
-  /**
    * The {@link Stating}s which occur in all models created by resolvers
    * created by this factory.
    */
@@ -105,8 +100,6 @@
     rdfType = initializer.preallocate(new URIReferenceImpl(RDF.TYPE));
     initializer.preallocate(new URIReferenceImpl(modelTypeURI));
 
-    systemModel = initializer.getSystemModel();
-
     // Claim mulgara:MemoryModel
     initializer.addModelType(modelTypeURI, this);
 
@@ -136,7 +129,6 @@
 
   public void setDatabaseMetadata(DatabaseMetadata metadata) {
     rdfType = metadata.getRdfTypeNode();
-    systemModel = metadata.getSystemModelNode();
   }
 
 
@@ -222,9 +214,7 @@
   ) throws ResolverFactoryException {
     if (logger.isDebugEnabled()) logger.debug("Creating memory resolver");
     return new MemoryResolver(resolverSession,
-                              systemResolver,
                               rdfType,
-                              systemModel,
                               modelTypeURI,
                               statingSet);
   }
@@ -234,8 +224,9 @@
     assert sessionFactory != null;
     if (logger.isDebugEnabled()) logger.debug("Creating memory resolver factory");
     try {
-      return new MemoryResolver(rdfType, systemModel, modelTypeURI, statingSet,
-                                (XAResolverSession) sessionFactory.newWritableResolverSession());
+      return new MemoryResolver(rdfType, modelTypeURI, statingSet,
+                                (XAResolverSession) sessionFactory.newWritableResolverSession(),
+                                this);
     } catch (ResolverSessionFactoryException er) {
       throw new ResolverFactoryException("Failed to obtain a new ResolverSession", er);
     }

Modified: branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *    Migration to AbstractXAResource copyright 2008 The Topaz Foundation
  *
  * [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
@@ -27,23 +28,15 @@
 
 package org.mulgara.resolver.memory;
 
-// Java 2 standard packages
-import java.util.*;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-// Third party packages
-import org.apache.log4j.Logger;
-
-
+import org.mulgara.resolver.spi.AbstractXAResource;
+import org.mulgara.resolver.spi.AbstractXAResource.RMInfo;
+import org.mulgara.resolver.spi.AbstractXAResource.TxInfo;
+import org.mulgara.resolver.spi.ResolverFactory;
 import org.mulgara.store.xa.SimpleXAResource;
-import org.mulgara.store.xa.SimpleXAResourceException;
 import org.mulgara.store.xa.XAResolverSession;
 
 /**
- * A dummy implementation of the {@link XAResource} interface which logs the
- * calls made to it, but otherwise ignores them.
+ * Implements the XAResource for the {@link MemoryResolver}.
  *
  * @created 2004-05-12
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
@@ -54,38 +47,8 @@
  *   Technoogies, Inc.</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-
-public class MemoryXAResource implements XAResource
-{
-  /** Logger.  */
-  private static final Logger logger =
-    Logger.getLogger(MemoryXAResource.class.getName());
-
-  /**
-   * Map from keyed from the {@link Integer} value of the various flags
-   * defined in {@link XAResource} and mapping to the formatted name for that
-   * flag.
-   */
-  private final static Map flagMap = new HashMap();
-
-  static {
-    flagMap.put(new Integer(XAResource.TMENDRSCAN),   "TMENDRSCAN");
-    flagMap.put(new Integer(XAResource.TMFAIL),       "TMFAIL");
-    flagMap.put(new Integer(XAResource.TMJOIN),       "TMJOIN");
-    flagMap.put(new Integer(XAResource.TMONEPHASE),   "TMONEPHASE");
-    flagMap.put(new Integer(XAResource.TMRESUME),     "TMRESUME");
-    flagMap.put(new Integer(XAResource.TMSTARTRSCAN), "TMSTARTRSCAN");
-    flagMap.put(new Integer(XAResource.TMSUCCESS),    "TMSUCCESS");
-    flagMap.put(new Integer(XAResource.TMSUCCESS),    "TMSUSPEND");
-  }
-
-  /** The transaction timeout value in seconds.  */
-  private int transactionTimeout = 0;
-
-  private XAResolverSession session;
-  private boolean rollback;
-  private Xid xid;
-
+public class MemoryXAResource
+    extends AbstractXAResource<RMInfo<MemoryXAResource.MemoryTxInfo>,MemoryXAResource.MemoryTxInfo> {
   //
   // Constructor
   //
@@ -94,209 +57,56 @@
    * Construct a {@link MemoryXAResource} with a specified transaction timeout.
    *
    * @param transactionTimeout  transaction timeout period, in seconds
+   * @param session             the underlying resolver-session to use
+   * @param resolverFactory     the resolver-factory we belong to
    */
   public MemoryXAResource(int transactionTimeout,
-                          XAResolverSession session)
-  {
-    logger.debug("<init> Creating MemoryXAResource: " + this);
-    this.transactionTimeout = transactionTimeout * 100;
-    this.session = session;
-    this.rollback = false;
+                          XAResolverSession session,
+                          ResolverFactory resolverFactory) {
+    super(transactionTimeout, resolverFactory, newTxInfo(session));
   }
 
-  //
-  // Methods implementing XAResource
-  //
-
-  public void start(Xid xid, int flags) throws XAException
-  {
-    logger.debug("Start " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
-    switch (flags) {
-      case XAResource.TMRESUME:
-        logger.debug("Resuming transaction on " + System.identityHashCode(xid));
-        break;
-      case XAResource.TMNOFLAGS:
-        try {
-          session.refresh(new SimpleXAResource[] {});
-          this.xid = xid;
-        } catch (SimpleXAResourceException es) {
-          logger.warn("Failed to refresh phases", es);
-          throw new XAException(XAException.XAER_RMFAIL);
-        }
-        break;
-      default:
-        rollback = true;
-        logger.error("Unrecognised flags in start: " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
-        throw new XAException(XAException.XAER_INVAL);
-    }
+  protected RMInfo<MemoryTxInfo> newResourceManager() {
+    return new RMInfo<MemoryTxInfo>();
   }
 
-  public int prepare(Xid xid) throws XAException
-  {
-    logger.debug("Prepare " + System.identityHashCode(xid));
-    logger.debug("Prepare always returns XA_OK, never XA_RDONLY");
-
-    if (rollback) {
-      logger.error("Attempting to prepare in failed transaction");
-      throw new XAException(XAException.XA_RBROLLBACK);
-    }
-    if (!xid.equals(this.xid)) {
-      logger.error("Attempting to prepare unknown transaction.");
-      throw new XAException(XAException.XAER_NOTA);
-    }
-
-    try {
-      session.prepare();
-    } catch (SimpleXAResourceException es) {
-      logger.warn("Attempt to prepare store failed", es);
-      throw new XAException(XAException.XA_RBROLLBACK);
-    }
-
-    return XA_OK;
+  private static MemoryTxInfo newTxInfo(XAResolverSession session) {
+    MemoryTxInfo ti = new MemoryTxInfo();
+    ti.session = session;
+    return ti;
   }
 
-  public void commit(Xid xid, boolean onePhase) throws XAException
-  {
-    logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
-    if (rollback) {
-      logger.error("Attempting to commit in failed transaction");
-      throw new XAException(XAException.XA_RBROLLBACK);
-    }
-    if (!xid.equals(this.xid)) {
-      logger.error("Attempting to commit unknown transaction.");
-      throw new XAException(XAException.XAER_NOTA);
-    }
+  //
+  // Methods implementing XAResource
+  //
 
-    try {
-      if (onePhase) {
-        // Check return value is XA_OK.
-        prepare(xid);
-      }
-    } catch (Throwable th) {
-      this.rollback = true;
-      logger.error("Attempt to prepare in onePhaseCommit failed.", th);
-      throw new XAException(XAException.XA_RBROLLBACK);
+  protected void doStart(MemoryTxInfo tx, int flags, boolean isNew) throws Exception {
+    if (flags == TMNOFLAGS || flags == TMJOIN) {
+      tx.session.refresh(new SimpleXAResource[] {});
     }
-
-    try {
-      session.commit();
-    } catch (Throwable th) {
-      // This is a serious problem since the database is now in an
-      // inconsistent state.
-      // Make sure the exception is logged.
-      logger.fatal("Failed to commit resource in transaction " + xid, th);
-      throw new XAException(XAException.XAER_RMERR);
-    }
   }
 
-  public void end(Xid xid, int flags) throws XAException
-  {
-    logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+  protected void doEnd(MemoryTxInfo tx, int flags) {
   }
 
-  public void forget(Xid xid) throws XAException
-  {
-    logger.debug("Forget xid=" + System.identityHashCode(xid));
+  protected int doPrepare(MemoryTxInfo tx) throws Exception {
+    tx.session.prepare();
+    return XA_OK;
   }
 
-  public int getTransactionTimeout() throws XAException
-  {
-    logger.debug("Get transaction timeout: " + transactionTimeout);
-    return transactionTimeout;
+  protected void doCommit(MemoryTxInfo tx) throws Exception {
+    tx.session.commit();
   }
 
-  public boolean isSameRM(XAResource xaResource) throws XAException
-  {
-    logger.debug("Is same resource manager? " + (xaResource == this) + " :: " + xaResource + " on " + this);
-    return xaResource == this;
+  protected void doRollback(MemoryTxInfo tx) throws Exception {
+    tx.session.rollback();
   }
 
-  public Xid[] recover(int flag) throws XAException
-  {
-    logger.debug("Recover flag=" + formatFlags(flag));
-    throw new XAException(XAException.XAER_RMERR);
+  protected void doForget(MemoryTxInfo tx) {
   }
 
-  public void rollback(Xid xid) throws XAException
-  {
-    logger.debug("Rollback " + System.identityHashCode(xid));
-
-    boolean fatalError = false;
-
-    if (!xid.equals(this.xid)) {
-      logger.error("Attempting to rollback unknown transaction.");
-      fatalError = true;
-    }
-
-    try {
-      session.rollback();
-    } catch (Throwable th) {
-      // This is a serious problem since the database is now in an
-      // inconsistent state.
-      // Make sure the exception is logged.
-      logger.fatal("Failed to rollback resource in transaction " + xid, th);
-      fatalError = true;
-    }
-
-    if (fatalError) {
-      logger.fatal("Fatal error occured while rolling back transaction " + xid + " in manager for " + this.xid);
-      throw new XAException(XAException.XAER_RMERR);
-    }
+  static class MemoryTxInfo extends TxInfo {
+    /** the underlying resolver-session to use */
+    public XAResolverSession session;
   }
-
-  public boolean setTransactionTimeout(int transactionTimeout)
-    throws XAException
-  {
-    logger.debug("Set transaction timeout: " + transactionTimeout);
-    this.transactionTimeout = transactionTimeout;
-    return true;
-  }
-
-  //
-  // Internal methods
-  //
-
-  /**
-   * Format bitmasks defined by {@link XAResource}.
-   *
-   * @param flags  a bitmask composed from the constants defined in
-   *   {@link XAResource}
-   * @return a formatted representation of the <var>flags</var>
-   */
-  private static String formatFlags(int flags)
-  {
-    // Short-circuit evaluation if we've been explicitly passed no flags
-    if (flags == XAResource.TMNOFLAGS) {
-      return "TMNOFLAGS";
-    }
-
-    StringBuffer buffer = new StringBuffer();
-
-    // Add any flags that are present
-    for (Iterator i = flagMap.entrySet().iterator(); i.hasNext(); ) {
-      Map.Entry entry = (Map.Entry)i.next();
-      int entryFlag = ((Integer)entry.getKey()).intValue();
-
-      // If this flag is present, add it to the formatted output and remove
-      // from the bitmask
-      if ((entryFlag & flags) == entryFlag) {
-        if (buffer.length() > 0) {
-          buffer.append(",");
-        }
-        buffer.append(entry.getValue());
-        flags &= ~entryFlag;
-      }
-    }
-
-    // We would expect to have removed all flags by this point
-    // If there's some unknown flag we've missed, format it as hexadecimal
-    if (flags != 0) {
-      if (buffer.length() > 0) {
-        buffer.append(",");
-      }
-      buffer.append("0x").append(Integer.toHexString(flags));
-    }
-
-    return buffer.toString();
-  }
 }

Copied: branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java (from rev 722, trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2008 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+
+package org.mulgara.resolver.spi;
+
+// Java 2 standard packages
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+/**
+ * A skeleton XAResource implementation. This handles the basic
+ * resource-manager and transaction management and ensures correct {@link
+ * #isSameRM} implementation. Subclasses must implement the actual
+ * functionality in the {@link #doStart}, {@link #doPrepare}, {@link
+ * #doCommit}, and {@link #doRollback} methods.
+ *
+ * @created 2008-02-16
+ * @author Ronald Tschalär
+ * @licence Apache License v2.0
+ */
+public abstract class AbstractXAResource<R extends AbstractXAResource.RMInfo<T>,T extends AbstractXAResource.TxInfo>
+    extends DummyXAResource {
+  /** Logger.  */
+  private static final Logger logger =
+    Logger.getLogger(AbstractXAResource.class.getName());
+
+  protected static final Map<ResolverFactory,RMInfo<? extends TxInfo>> resourceManagers =
+    new WeakHashMap<ResolverFactory,RMInfo<? extends TxInfo>>();
+
+  protected final R resourceManager;
+  protected final T tmpTxInfo;
+
+
+  //
+  // Constructor
+  //
+
+  /**
+   * Construct an XAResource.
+   *
+   * @param transactionTimeout  transaction timeout period, in seconds
+   * @param resolverFactory     the resolver-factory we belong to
+   * @param txInfo              the initial transaction-info
+   */
+  public AbstractXAResource(int transactionTimeout,
+                            ResolverFactory resolverFactory,
+                            T txInfo) {
+    super(transactionTimeout);
+
+    synchronized (resourceManagers) {
+      @SuppressWarnings("unchecked")
+      R rmgr = (R) resourceManagers.get(resolverFactory);
+      if (rmgr == null)
+        resourceManagers.put(resolverFactory, rmgr = newResourceManager());
+      this.resourceManager = rmgr;
+    }
+
+    this.tmpTxInfo = txInfo;
+  }
+
+  /**
+   * Create a new resource-manager instance - invoked only from the
+   * constructor and only when no resource-manager instance exists for the
+   * given resolver-factory.
+   */
+  protected abstract R newResourceManager();
+
+  //
+  // Methods implementing XAResource
+  //
+
+  public void start(Xid xid, int flags) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Start xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+      logger.debug("xid.format=" + xid.getFormatId() + " xid.gblTxId=" + Arrays.toString(xid.getGlobalTransactionId()) + " xid.brnchQual=" + Arrays.toString(xid.getBranchQualifier()));
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    boolean isNew = false;
+
+    switch (flags) {
+      case XAResource.TMRESUME:
+        if (tx == null) {
+          logger.error("Attempting to resume unknown transaction.");
+          throw new XAException(XAException.XAER_NOTA);
+        }
+        if (logger.isDebugEnabled()) {
+          logger.debug("Resuming transaction on xid=" + System.identityHashCode(xid));
+        }
+        break;
+
+      case XAResource.TMNOFLAGS:
+        if (tx != null) {
+          logger.warn("Received plain start for existing tx");
+          logger.warn("xid.format=" + xid.getFormatId() + " xid.gblTxId=" + Arrays.toString(xid.getGlobalTransactionId()) + " xid.brnchQual=" + Arrays.toString(xid.getBranchQualifier()));
+          throw new XAException(XAException.XAER_DUPID);
+        }
+        // fallthrough
+
+      case XAResource.TMJOIN:
+        if (tx == null) {
+          resourceManager.transactions.put(new XidWrapper(xid), tx = tmpTxInfo);
+          tx.xid = xid;
+          isNew = true;
+        }
+        break;
+
+      default:
+        // XXX: is this correct? Or should we actually roll back here?
+        if (tx != null)
+          tx.rollback = true;
+        logger.error("Unrecognised flags in start: xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+        throw new XAException(XAException.XAER_INVAL);
+    }
+
+    try {
+      doStart(tx, flags, isNew);
+    } catch (Throwable t) {
+      logger.warn("Failed to do start", t);
+      resourceManager.transactions.remove(new XidWrapper(xid));
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public void end(Xid xid, int flags) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    if (tx == null) {
+      logger.error("Attempting to end unknown transaction.");
+      throw new XAException(XAException.XAER_NOTA);
+    }
+
+    try {
+      doEnd(tx, flags);
+    } catch (Throwable t) {
+      logger.warn("Failed to do end", t);
+      resourceManager.transactions.remove(new XidWrapper(xid));
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public int prepare(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Prepare xid=" + System.identityHashCode(xid));
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    if (tx == null) {
+      logger.error("Attempting to prepare unknown transaction.");
+      throw new XAException(XAException.XAER_NOTA);
+    }
+
+    if (tx.rollback) {
+      logger.info("Attempting to prepare in failed transaction");
+      rollback(xid);
+      throw new XAException(XAException.XA_RBROLLBACK);
+    }
+
+    try {
+      int sts = doPrepare(tx);
+      if (sts == XA_RDONLY)
+        resourceManager.transactions.remove(new XidWrapper(xid));
+      return sts;
+    } catch (Throwable t) {
+      logger.warn("Attempt to prepare failed", t);
+      rollback(xid);
+      throw new XAException(XAException.XA_RBROLLBACK);
+    }
+  }
+
+  public void commit(Xid xid, boolean onePhase) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    if (tx == null) {
+      logger.error("Attempting to commit unknown transaction.");
+      throw new XAException(XAException.XAER_NOTA);
+    }
+    if (tx.rollback) {
+      logger.error("Attempting to commit in failed transaction");
+      rollback(xid);
+      throw new XAException(XAException.XA_RBROLLBACK);
+    }
+
+    try {
+      if (onePhase) {
+        int sts = doPrepare(tx);
+        if (sts == XA_RDONLY) {
+          resourceManager.transactions.remove(new XidWrapper(xid));
+          return;
+        }
+      }
+    } catch (Throwable th) {
+      logger.error("Attempt to prepare in onePhaseCommit failed.", th);
+      rollback(xid);
+      throw new XAException(XAException.XA_RBROLLBACK);
+    }
+
+    boolean clean = true;
+    try {
+      doCommit(tx);
+    } catch (XAException xae) {
+      if (isHeuristic(xae)) {
+        clean = false;
+      }
+      throw xae;
+    } catch (Throwable th) {
+      // This is a serious problem since the database is now in an
+      // inconsistent state.
+      // Make sure the exception is logged.
+      logger.fatal("Failed to commit resource in transaction " + xid, th);
+      throw new XAException(XAException.XAER_RMERR);
+    } finally {
+      if (clean) {
+        resourceManager.transactions.remove(new XidWrapper(xid));
+      }
+    }
+  }
+
+  public void rollback(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Rollback xid=" + System.identityHashCode(xid));
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    if (tx == null) {
+      logger.error("Attempting to rollback unknown transaction.");
+      throw new XAException(XAException.XAER_NOTA);
+    }
+
+    boolean clean = true;
+    try {
+      doRollback(tx);
+    } catch (XAException xae) {
+      if (isHeuristic(xae)) {
+        clean = false;
+      }
+      throw xae;
+    } catch (Throwable th) {
+      // This is a serious problem since the database is now in an
+      // inconsistent state.
+      // Make sure the exception is logged.
+      logger.fatal("Failed to rollback resource in transaction " + xid, th);
+      throw new XAException(XAException.XAER_RMERR);
+    } finally {
+      if (clean) {
+        resourceManager.transactions.remove(new XidWrapper(xid));
+      }
+    }
+  }
+
+  public void forget(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Forget xid=" + System.identityHashCode(xid));
+    }
+
+    T tx = resourceManager.transactions.get(new XidWrapper(xid));
+    if (tx == null) {
+      logger.error("Attempting to forget unknown transaction.");
+      throw new XAException(XAException.XAER_NOTA);
+    }
+
+    boolean clean = true;
+    try {
+      doForget(tx);
+    } catch (XAException xae) {
+      if (xae.errorCode == XAException.XAER_RMERR) {
+        clean = false;
+      }
+      throw xae;
+    } catch (Throwable th) {
+      logger.error("Failed to forget transaction " + xid, th);
+      clean = false;
+      throw new XAException(XAException.XAER_RMERR);
+    } finally {
+      if (clean) {
+        resourceManager.transactions.remove(new XidWrapper(xid));
+      }
+    }
+  }
+
+  public Xid[] recover(int flag) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Recover flag=" + formatFlags(flag));
+    }
+
+    throw new XAException(XAException.XAER_RMERR);
+  }
+
+  public boolean isSameRM(XAResource xaResource) throws XAException {
+    boolean same = (xaResource instanceof AbstractXAResource) &&
+      ((AbstractXAResource)xaResource).resourceManager == resourceManager;
+
+    if (logger.isDebugEnabled()) {
+      logger.debug("Is same resource manager? " + same + " :: " + xaResource + " on " + this);
+    }
+
+    return same;
+  }
+
+  /** 
+   * Invoked on start with valid flags and tx state.
+   * 
+   * @param tx     the transaction being started; always non-null
+   * @param flags  one of TMNOFLAGS, TMRESUME, or TMJOIN
+   * @param isNew  true if <var>tx</var> was created as part of this start()
+   * @throws Exception 
+   */
+  protected abstract void doStart(T tx, int flags, boolean isNew) throws Exception;
+
+  /** 
+   * Invoked on end().
+   * 
+   * @param tx     the transaction being ended; always non-null
+   * @param flags  one of TMSUCCESS, TMFAIL, or TMSUSPEND
+   * @throws Exception 
+   */
+  protected abstract void doEnd(T tx, int flags) throws Exception;
+
+  /** 
+   * Invoked on prepare() or commit(onePhase=true).
+   * 
+   * @param tx  the transaction being prepared; always non-null
+   * @return XA_OK or XA_RDONLY
+   * @throws Exception 
+   */
+  protected abstract int doPrepare(T tx) throws Exception;
+
+  /** 
+   * Invoked on commit().
+   * 
+   * @param tx  the transaction being committed; always non-null
+   * @throws Exception 
+   */
+  protected abstract void doCommit(T tx) throws Exception;
+
+  /** 
+   * Invoked on (explicit or implicit) rollback().
+   * 
+   * @param tx  the transaction being rolled back; always non-null
+   * @throws Exception 
+   */
+  protected abstract void doRollback(T tx) throws Exception;
+
+  /** 
+   * Invoked on forget().
+   * 
+   * @param tx  the transaction to forget; always non-null
+   * @throws Exception 
+   */
+  protected abstract void doForget(T tx) throws Exception;
+
+  private static boolean isHeuristic(XAException xae) {
+    return (xae.errorCode == XAException.XA_HEURHAZ || xae.errorCode == XAException.XA_HEURCOM ||
+            xae.errorCode == XAException.XA_HEURRB  || xae.errorCode == XAException.XA_HEURMIX);
+  }
+
+
+  /** The resource-manager info */
+  public static class RMInfo<T extends TxInfo> {
+    /** the list of active transactions */
+    public final Map<XidWrapper,T> transactions =
+      Collections.synchronizedMap(new HashMap<XidWrapper,T>());
+  }
+
+  /** The info pertaining to a single transaction */
+  public static class TxInfo {
+    /** the underlying Xid of this transaction; not valid till the first start() */
+    public Xid xid;
+    /** true if this transaction has been marked for rollback */
+    public boolean rollback;
+  }
+
+  /**
+   * Xid-wrapper that implements hashCode() and equals(). JTA does not require
+   * Xid's to implement hashCode() and equals(), so in order to be able to use
+   * them as keys in a map we need to wrap them with something that implements
+   * them based on the individual fields of the Xid.
+   */
+  public static class XidWrapper {
+    private final Xid xid;
+    private final int hash;
+
+    public XidWrapper(Xid xid) {
+      this.xid = xid;
+      this.hash = Arrays.hashCode(xid.getBranchQualifier());
+    }
+
+    public int hashCode() {
+      return hash;
+    }
+
+    public boolean equals(Object other) {
+      Xid o;
+
+      if (other instanceof XidWrapper) {
+        o = ((XidWrapper)other).xid;
+      } else if (other instanceof Xid) {
+        o = (Xid)other;
+      } else {
+        return false;
+      }
+
+      if (o == xid)
+        return true;
+      return o.getFormatId() == xid.getFormatId() &&
+             Arrays.equals(o.getGlobalTransactionId(), xid.getGlobalTransactionId()) &&
+             Arrays.equals(o. getBranchQualifier(), xid. getBranchQualifier());
+    }
+  }
+}

Copied: branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/BackupRestoreSession.java (from rev 722, trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/BackupRestoreSession.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/BackupRestoreSession.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/BackupRestoreSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,51 @@
+
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Andrae Muys
+ * Copyright (c) 2008 Andrae Muys <andrae at muys.id.au>
+ * All Rights Reserved.
+ */
+package org.mulgara.resolver.spi;
+
+// Third party packages
+
+// Local packages
+import org.mulgara.store.nodepool.NodePool;
+import org.mulgara.store.stringpool.SPObject;
+import org.mulgara.store.stringpool.StringPoolException;
+
+/**
+ * An interface to the string-pool required by the Backup and Restore
+ * Operations.
+ *
+ *  Note: This interface is a temporary fix until the model-name deconflation
+ *  work is put in place - at which point this we will hopefully be able to
+ *  rely on the string-pool primitives in ResolverSession.
+ *
+ * @created 2008-03-25
+ * @copyright &copy;2008 <a href="mailto:andrae at muys.id.au">Andrae Muys</a>
+ * @licence Open Software Licence v3.0
+ */
+
+public interface BackupRestoreSession
+{
+  public static final long NONE = NodePool.NONE;
+  /**
+   * Find a single object in the persistent string pool.
+   *
+   * @param gNode The graph node to find.
+   * @return the SPObject corresponding to <var>gNode</var>, or
+   * <code>null</code> if the node is not in the pool.
+   * @throws StringPoolException if an internal error occurs.
+   */
+  public SPObject findSPObject(long gNode) throws StringPoolException;
+}

Modified: branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -54,15 +54,14 @@
 public class DummyXAResource implements XAResource
 {
   /** Logger.  */
-  private static final Logger logger =
-    Logger.getLogger(DummyXAResource.class.getName());
+  private static final Logger logger = Logger.getLogger(DummyXAResource.class.getName());
 
   /**
    * Map from keyed from the {@link Integer} value of the various flags
    * defined in {@link XAResource} and mapping to the formatted name for that
    * flag.
    */
-  private final static Map flagMap = new HashMap();
+  protected final static Map<Integer,String> flagMap = new HashMap<Integer,String>();
 
   static {
     flagMap.put(new Integer(XAResource.TMENDRSCAN),   "TMENDRSCAN");
@@ -76,20 +75,28 @@
   }
 
   /** The transaction timeout value in seconds.  */
-  private int transactionTimeout = 0;
+  protected int transactionTimeout = 0;
 
   //
   // Constructor
   //
 
   /**
+   * Construct a {@link DummyXAResource} with a default 10 second transaction timeout.
+   */
+  public DummyXAResource() {
+    this(10);
+  }
+
+  /**
    * Construct a {@link DummyXAResource} with a specified transaction timeout.
    *
    * @param transactionTimeout  transaction timeout period, in seconds
    */
-  public DummyXAResource(int transactionTimeout)
-  {
-    logger.debug("Creating DummyXAResource with timeout " + transactionTimeout);
+  public DummyXAResource(int transactionTimeout) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Creating " + getClass().getName() + " with timeout " + transactionTimeout);
+    }
     this.transactionTimeout = transactionTimeout;
   }
 
@@ -97,61 +104,70 @@
   // Methods implementing XAResource
   //
 
-  public void commit(Xid xid, boolean onePhase) throws XAException
-  {
-    logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
+  public void commit(Xid xid, boolean onePhase) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
+    }
   }
 
-  public void end(Xid xid, int flags) throws XAException
-  {
-    logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+  public void end(Xid xid, int flags) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+    }
   }
 
-  public void forget(Xid xid) throws XAException
-  {
-    logger.debug("Forget xid=" + System.identityHashCode(xid));
+  public void forget(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Forget xid=" + System.identityHashCode(xid));
+    }
   }
 
-  public int getTransactionTimeout() throws XAException
-  {
-    logger.debug("Get transaction timeout: " + transactionTimeout);
+  public int getTransactionTimeout() throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Get transaction timeout: " + transactionTimeout);
+    }
     return transactionTimeout;
   }
 
-  public boolean isSameRM(XAResource xaResource) throws XAException
-  {
-    logger.debug("Is same resource manager? " + (xaResource == this));
+  public boolean isSameRM(XAResource xaResource) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Is same resource manager? " + (xaResource == this));
+    }
     return xaResource == this;
   }
 
-  public int prepare(Xid xid) throws XAException
-  {
-    logger.debug("Prepare " + System.identityHashCode(xid));
+  public int prepare(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Prepare " + System.identityHashCode(xid));
+    }
     return XA_OK;
   }
 
-  public Xid[] recover(int flag) throws XAException
-  {
-    logger.debug("Recover flag=" + formatFlags(flag));
+  public Xid[] recover(int flag) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Recover flag=" + formatFlags(flag));
+    }
     throw new XAException(XAException.XAER_RMERR);
   }
 
-  public void rollback(Xid xid) throws XAException
-  {
-    logger.debug("Rollback " + System.identityHashCode(xid));
+  public void rollback(Xid xid) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Rollback " + System.identityHashCode(xid));
+    }
   }
 
-  public boolean setTransactionTimeout(int transactionTimeout)
-    throws XAException
-  {
-    logger.debug("Set transaction timeout: " + transactionTimeout);
+  public boolean setTransactionTimeout(int transactionTimeout) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Set transaction timeout: " + transactionTimeout);
+    }
     this.transactionTimeout = transactionTimeout;
     return true;
   }
 
-  public void start(Xid xid, int flags) throws XAException
-  {
-    logger.debug("Start " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+  public void start(Xid xid, int flags) throws XAException {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Start " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+    }
   }
 
   //
@@ -161,23 +177,20 @@
   /**
    * Format bitmasks defined by {@link XAResource}.
    *
-   * @param flags  a bitmask composed from the constants defined in
-   *   {@link XAResource}
+   * @param flags  a bitmask composed from the constants defined in {@link XAResource}
    * @return a formatted representation of the <var>flags</var>
    */
-  private static String formatFlags(int flags)
-  {
+  protected static final String formatFlags(int flags) {
     // Short-circuit evaluation if we've been explicitly passed no flags
     if (flags == XAResource.TMNOFLAGS) {
       return "TMNOFLAGS";
     }
 
-    StringBuffer buffer = new StringBuffer();
+    StringBuilder buffer = new StringBuilder();
 
     // Add any flags that are present
-    for (Iterator i = flagMap.entrySet().iterator(); i.hasNext(); ) {
-      Map.Entry entry = (Map.Entry)i.next();
-      int entryFlag = ((Integer)entry.getKey()).intValue();
+    for (Map.Entry<Integer,String> entry : flagMap.entrySet()) {
+      int entryFlag = entry.getKey().intValue();
 
       // If this flag is present, add it to the formatted output and remove
       // from the bitmask

Modified: branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/ResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/ResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/ResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -61,7 +61,7 @@
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 
-public interface ResolverSession
+public interface ResolverSession extends BackupRestoreSession
 {
   /**
    * Convert session-local node numbers to globally valid RDF nodes.
@@ -196,4 +196,11 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory();
+
+  /**
+   * DO NOT USE: This is solely for the use of RestoreOperation.
+   * Will be removed from this interface as soon as RestoreOperation can be
+   * refactored to no longer require it.
+   */
+  public long findGNode(SPObject spObject) throws StringPoolException;
 }

Modified: branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TripleSetWrapperStatements.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TripleSetWrapperStatements.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TripleSetWrapperStatements.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -71,8 +71,8 @@
   
   TObjectLongHashMap nodeMap;
 
-  Set<Triple> triples;
-  Iterator<Triple> iter;
+  Set<? extends Triple> triples;
+  Iterator<? extends Triple> iter;
   Triple currentTriple;
   boolean persistent;
 
@@ -80,7 +80,7 @@
   // Constructors
   //
 
-  public TripleSetWrapperStatements(Set<Triple> triples, ResolverSession resolverSession, int persistent)
+  public TripleSetWrapperStatements(Set<? extends Triple> triples, ResolverSession resolverSession, int persistent)
       throws TuplesException {
     this.triples = triples;
     this.resolverSession = resolverSession;

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreDuplicateResolution.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreDuplicateResolution.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreDuplicateResolution.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,7 +30,7 @@
 package org.mulgara.resolver.store;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Standard Java packages
 import java.util.*;
@@ -80,8 +80,7 @@
  */
 class StatementStoreDuplicateResolution extends AbstractTuples implements Resolution {
 
-  protected static Category logger =
-      Category.getInstance(StatementStoreDuplicateResolution.class.getName());
+  protected static Logger logger = Logger.getLogger(StatementStoreDuplicateResolution.class);
 
   /**
    * The constraint these tuples were generated to satisfy.

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreInverseResolution.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreInverseResolution.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreInverseResolution.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,7 +30,7 @@
 package org.mulgara.resolver.store;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Standard Java packages
 import java.util.*;
@@ -71,8 +71,7 @@
  */
 class StatementStoreInverseResolution extends AbstractTuples implements Resolution {
 
-  protected static Category logger =
-      Category.getInstance(StatementStoreInverseResolution.class.getName());
+  protected static final Logger logger = Logger.getLogger(StatementStoreInverseResolution.class);
 
   /**
    * The constraint these tuples were generated to satisfy.

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolution.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolution.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolution.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 package org.mulgara.resolver.store;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Standard Java packages
 import java.util.*;
@@ -72,8 +72,7 @@
   private final static long ROWCOUNT_UNCALCULATED = -1;
   private final static int ROWCARD_UNCALCULATED = -1;
 
-  private final static Category logger =
-      Category.getInstance(StatementStoreResolution.class.getName());
+  private final static Logger logger = Logger.getLogger(StatementStoreResolution.class);
 
   /** The constraint these tuples were generated to satisfy. */
   private Constraint constraint;

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,9 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *    Move to associate XAResource with Resolver Factory
+ *     copyright 2008 The Topaz Foundation
  *
  * [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
@@ -131,7 +133,8 @@
                          long systemModel,
                          URI modelTypeURI,
                          XAResolverSession resolverSession,
-                         XAStatementStore statementStore)
+                         XAStatementStore statementStore,
+                         ResolverFactory resolverFactory)
       throws IllegalArgumentException, ResolverFactoryException
   {
     // Validate parameters
@@ -153,7 +156,8 @@
     this.xaresource = new StatementStoreXAResource(
         10,  // transaction timeout in seconds
         resolverSession,
-        new SimpleXAResource[] { statementStore });
+        new SimpleXAResource[] { statementStore },
+        resolverFactory);
   }
 
   StatementStoreResolver(Resolver systemResolver,
@@ -161,7 +165,8 @@
                          long systemModel,
                          URI modelTypeURI,
                          XAResolverSession resolverSession,
-                         XAStatementStore statementStore)
+                         XAStatementStore statementStore,
+                         ResolverFactory resolverFactory)
       throws IllegalArgumentException, ResolverFactoryException
   {
     // Validate parameters
@@ -182,7 +187,8 @@
     this.xaresource = new StatementStoreXAResource(
         10,  // transaction timeout in seconds
         resolverSession,
-        new SimpleXAResource[] { statementStore });
+        new SimpleXAResource[] { statementStore },
+        resolverFactory);
   }
 
 
@@ -374,7 +380,7 @@
                                                + resolverSession.globalize(statements.getObject()) + " "
                                                + resolverSession.globalize(model) + "]", e);
       } catch (Exception eg) {
-	      throw new ResolverException("Failed to globalize in debug", eg);
+        throw new ResolverException("Failed to globalize in debug", eg);
       }
       throw new ResolverException("Couldn't make statement " + occurs + " in " + model, e);
     } catch (TuplesException e) {
@@ -478,7 +484,7 @@
    * @throws StringPoolException
    */
   public SPObject findStringPoolObject(long gNode) throws StringPoolException {
-    return xaResolverSession.findStringPoolObject(gNode);
+    return resolverSession.findStringPoolObject(gNode);
   }
 
   /**
@@ -488,10 +494,17 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
-
     return resolverSession.getSPObjectFactory();
   }
 
+  public SPObject findSPObject(long gNode) throws StringPoolException {
+    return resolverSession.findSPObject(gNode);
+  }
+
+  public long findGNode(SPObject spObject) throws StringPoolException {
+    return resolverSession.findGNode(spObject);
+  }
+
   //
   // Internal methods
   //

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -195,7 +195,8 @@
               : (XAResolverSession) resolverSessionFactory.newReadOnlyResolverSession(),
           allowWrites
               ? statementStore.newWritableStatementStore()
-              : statementStore.newReadOnlyStatementStore());
+              : statementStore.newReadOnlyStatementStore(),
+          this);
     } catch (ResolverSessionFactoryException er) {
       throw new ResolverFactoryException(
           "Failed to obtain a new ResolverSession", er);
@@ -216,7 +217,8 @@
           :
           (XAResolverSession) resolverSessionFactory.newReadOnlyResolverSession(),
           allowWrites ? statementStore.newWritableStatementStore()
-          : statementStore.newReadOnlyStatementStore());
+          : statementStore.newReadOnlyStatementStore(),
+          this);
     } catch (ResolverSessionFactoryException er) {
       throw new ResolverFactoryException(
           "Failed to obtain a new ResolverSession", er);

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -17,6 +17,7 @@
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
  * Contributor(s): N/A.
+ *   Migration to AbstractXAResource copyright 2008 The Topaz Foundation
  *
  * [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
@@ -28,22 +29,22 @@
 package org.mulgara.resolver.store;
 
 // Java 2 standard packages
-import java.util.*;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
+import java.util.HashSet;
+import java.util.Set;
 
 // Third party packages
 import org.apache.log4j.Logger;
 
-
+import org.mulgara.resolver.spi.AbstractXAResource;
+import org.mulgara.resolver.spi.AbstractXAResource.RMInfo;
+import org.mulgara.resolver.spi.AbstractXAResource.TxInfo;
+import org.mulgara.resolver.spi.ResolverFactory;
 import org.mulgara.store.xa.SimpleXAResource;
 import org.mulgara.store.xa.SimpleXAResourceException;
 import org.mulgara.store.xa.XAResolverSession;
 
 /**
- * A dummy implementation of the {@link XAResource} interface which logs the
- * calls made to it, but otherwise ignores them.
+ * Implements the XAResource for the {@link StatementStoreResolver}.
  *
  * @created 2004-05-12
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
@@ -55,40 +56,15 @@
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 
-public class StatementStoreXAResource implements XAResource
-{
+public class StatementStoreXAResource
+    extends AbstractXAResource<RMInfo<StatementStoreXAResource.StatementStoreTxInfo>, StatementStoreXAResource.StatementStoreTxInfo> {
   /** Logger.  */
   private static final Logger logger =
     Logger.getLogger(StatementStoreXAResource.class.getName());
 
-  /**
-   * Map from keyed from the {@link Integer} value of the various flags
-   * defined in {@link XAResource} and mapping to the formatted name for that
-   * flag.
-   */
-  private final static Map flagMap = new HashMap();
-
-  static {
-    flagMap.put(new Integer(XAResource.TMENDRSCAN),   "TMENDRSCAN");
-    flagMap.put(new Integer(XAResource.TMFAIL),       "TMFAIL");
-    flagMap.put(new Integer(XAResource.TMJOIN),       "TMJOIN");
-    flagMap.put(new Integer(XAResource.TMONEPHASE),   "TMONEPHASE");
-    flagMap.put(new Integer(XAResource.TMRESUME),     "TMRESUME");
-    flagMap.put(new Integer(XAResource.TMSTARTRSCAN), "TMSTARTRSCAN");
-    flagMap.put(new Integer(XAResource.TMSUCCESS),    "TMSUCCESS");
-    flagMap.put(new Integer(XAResource.TMSUSPEND),    "TMSUSPEND");
-  }
-
-  /** The transaction timeout value in seconds.  */
-  private int transactionTimeout = 0;
-
-  private SimpleXAResource[] resources;
-  private XAResolverSession session;
-  private boolean rollback;
-  private Xid xid;
   // Used to prevent multiple calls to prepare on the store layer.
   // Set of session's that have been prepared.
-  private static Set preparing = new HashSet();
+  public static Set<XAResolverSession> preparing = new HashSet<XAResolverSession>();
 
   //
   // Constructor
@@ -98,292 +74,127 @@
    * Construct a {@link StatementStoreXAResource} with a specified transaction timeout.
    *
    * @param transactionTimeout  transaction timeout period, in seconds
+   * @param session             the underlying resolver-session to use
+   * @param resources           
+   * @param resolverFactory     the resolver-factory we belong to
    */
   public StatementStoreXAResource(int transactionTimeout,
                                   XAResolverSession session,
-                                  SimpleXAResource[] resources)
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("<init> Creating StatementStoreXAResource: " + this);
-    }
-    this.transactionTimeout = transactionTimeout * 100;
-    this.resources = resources;
-    this.session = session;
+                                  SimpleXAResource[] resources,
+                                  ResolverFactory resolverFactory) {
+    super(transactionTimeout, resolverFactory, newTxInfo(session, resources));
   }
 
+  protected RMInfo<StatementStoreTxInfo> newResourceManager() {
+    return new RMInfo<StatementStoreTxInfo>();
+  }
+
+  private static StatementStoreTxInfo newTxInfo(XAResolverSession session,
+                                                SimpleXAResource[] resources) {
+    StatementStoreTxInfo ti = new StatementStoreTxInfo();
+    ti.session = session;
+    ti.resources = resources;
+    return ti;
+  }
+
   //
   // Methods implementing XAResource
   //
 
-  public void start(Xid xid, int flags) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Start " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
-    } 
-    switch (flags) {
-      case XAResource.TMNOFLAGS:
-        try {
-          session.refresh(resources);
-          this.xid = xid;
-          this.rollback = false;
-        } catch (SimpleXAResourceException es) {
-          logger.error("Failed to obtain phases", es);
-          throw new XAException(XAException.XAER_RMFAIL);
-        }
-        break;
-      case XAResource.TMRESUME:
-        if (!xid.equals(this.xid)) {
-          logger.error("Attempt to resume resource in wrong transaction.");
-          throw new XAException(XAException.XAER_INVAL);
-        }
-        break;
-      case XAResource.TMJOIN:
-        if (!xid.equals(this.xid)) {
-          logger.error("Attempt to join with wrong transaction.");
-          throw new XAException(XAException.XAER_INVAL);
-        }
-        break;
-      default:  // Currently fall-through.
-        rollback = true;
-        logger.warn("Unrecognised flags in start: " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
-        if (logger.isDebugEnabled()) {
-          logger.debug("This XAResource = " + System.identityHashCode(this.xid));
-        }
-        throw new XAException(XAException.XAER_INVAL);
+  protected void doStart(StatementStoreTxInfo tx, int flags, boolean isNew) throws Exception {
+    if (flags == TMNOFLAGS) {
+      tx.session.refresh(tx.resources);
     }
   }
 
-  public int prepare(Xid xid) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("XAResource " + this + " Prepare " + System.identityHashCode(xid) + " With Session: " + System.identityHashCode(session));
-    }
+  protected void doEnd(StatementStoreTxInfo tx, int flags) {
+  }
 
-    if (rollback) {
-      logger.error("Attempting to prepare in failed transaction");
-      throw new XAException(XAException.XA_RBROLLBACK);
-    }
-    if (!xid.equals(this.xid)) {
-      logger.error("Attempting to prepare unknown transaction.");
-      throw new XAException(XAException.XAER_NOTA);
-    }
-    synchronized(preparing) {
-      if (preparing.contains(session)) {
+  protected int doPrepare(StatementStoreTxInfo tx) throws Exception {
+    synchronized (preparing) {
+      if (preparing.contains(tx.session)) {
         return XA_OK;
       } else {
-        preparing.add(session);
+        preparing.add(tx.session);
       }
     }
 
     try {
-      session.prepare();
+      tx.session.prepare();
     } catch (SimpleXAResourceException es) {
-      logger.warn("Attempt to prepare store failed", es);
-      synchronized(preparing) {
-        preparing.remove(session);
+      synchronized (preparing) {
+        preparing.remove(tx.session);
       }
-      throw new XAException(XAException.XA_RBROLLBACK);
+      throw es;
     }
 
     return XA_OK;
   }
 
-  public void commit(Xid xid, boolean onePhase) throws XAException
-  {
+  protected void doCommit(StatementStoreTxInfo tx) throws Exception {
     try {
-      if (logger.isDebugEnabled()) {
-        logger.debug("XAResource " + this + " Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase + " session=" + System.identityHashCode(session));
-      }
-      if (rollback) {
-        logger.error("Attempting to commit in failed transaction");
-        throw new XAException(XAException.XA_RBROLLBACK);
-      }
-      if (!xid.equals(this.xid)) {
-        logger.error("Attempting to commit unknown transaction.");
-        throw new XAException(XAException.XAER_NOTA);
-      }
-      try {
-        if (onePhase) {
-          // Currently prepare only returns XA_OK, and throws an exception on failure.
-          prepare(xid);
-        }
-      } catch (Throwable th) {
-        this.rollback = true;
-        logger.error("Attempt to prepare in onePhaseCommit failed.", th);
-        throw new XAException(XAException.XA_RBROLLBACK);
-      }
-
-      try {
-        session.commit();
-      } catch (Throwable th) {
-        // This is a serious problem since the database is now in an
-        // inconsistent state.
-        // Make sure the exception is logged.
-        logger.fatal("Failed to commit resource in transaction " + xid, th);
-        throw new XAException(XAException.XAER_RMERR);
-      }
+      tx.session.commit();
     } finally {
-      cleanup("commit");
+      cleanup("commit", tx);
     }
-
   }
 
-  public void end(Xid xid, int flags) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
-    }
-  }
-
-  public void forget(Xid xid) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Forget xid=" + System.identityHashCode(xid));
-    }
+  protected void doForget(StatementStoreTxInfo tx) throws Exception {
     try {
-      synchronized(preparing) {
-        if (preparing.contains(session)) {
-          rollback(xid);
+      synchronized (preparing) {
+        if (preparing.contains(tx.session)) {
+          doRollback(tx);
         }
       }
     } finally {
-      cleanup("forget");
+      cleanup("forget", tx);
     }
   }
 
-  public int getTransactionTimeout() throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Get transaction timeout: " + transactionTimeout);
-    }
-    return transactionTimeout;
-  }
-
-  public boolean isSameRM(XAResource xaResource) throws XAException
-  {
-    return xaResource == this;
-  }
-
-  public Xid[] recover(int flag) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Recover flag=" + formatFlags(flag));
-    }
-    throw new XAException(XAException.XAER_RMERR);
-  }
-
-  public void rollback(Xid xid) throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Rollback " + System.identityHashCode(xid));
-    }
-
-    boolean fatalError = false;
-
-    if (!xid.equals(this.xid)) {
-      logger.error("Attempting to rollback unknown transaction.");
-      fatalError = true;
-    }
-
+  protected void doRollback(StatementStoreTxInfo tx) throws Exception {
     try {
-      if (logger.isDebugEnabled()) {
-        logger.debug("Rolling back phase");
-      }
-      session.rollback();
-    } catch (Throwable th) {
-      // This is a serious problem since the database is now in an
-      // inconsistent state.
-      // Make sure the exception is logged.
-      logger.fatal("Failed to rollback resource in transaction " + xid, th);
-      fatalError = true;
+      tx.session.rollback();
     } finally {
-      cleanup("rollback");
+      cleanup("rollback", tx);
     }
-
-    if (fatalError) {
-      logger.fatal("Fatal error occured while rolling back transaction " + xid + " in manager for " + this.xid);
-      throw new XAException(XAException.XAER_RMERR);
-    }
   }
 
-  public boolean setTransactionTimeout(int transactionTimeout)
-    throws XAException
-  {
-    if (logger.isDebugEnabled()) {
-      logger.debug("Set transaction timeout: " + transactionTimeout);
-    }
-    this.transactionTimeout = transactionTimeout;
-    return true;
-  }
-
   //
   // Internal methods
   //
 
-  /**
-   * Format bitmasks defined by {@link XAResource}.
-   *
-   * @param flags  a bitmask composed from the constants defined in
-   *   {@link XAResource}
-   * @return a formatted representation of the <var>flags</var>
-   */
-  private static String formatFlags(int flags)
-  {
-    // Short-circuit evaluation if we've been explicitly passed no flags
-    if (flags == XAResource.TMNOFLAGS) {
-      return "TMNOFLAGS";
+  private void cleanup(String operation, StatementStoreTxInfo tx) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Performing cleanup from " + operation);
     }
-
-    StringBuffer buffer = new StringBuffer();
-
-    // Add any flags that are present
-    for (Iterator i = flagMap.entrySet().iterator(); i.hasNext(); ) {
-      Map.Entry entry = (Map.Entry)i.next();
-      int entryFlag = ((Integer)entry.getKey()).intValue();
-
-      // If this flag is present, add it to the formatted output and remove
-      // from the bitmask
-      if ((entryFlag & flags) == entryFlag) {
-        if (buffer.length() > 0) {
-          buffer.append(",");
-        }
-        buffer.append(entry.getValue());
-        flags &= ~entryFlag;
-      }
-    }
-
-    // We would expect to have removed all flags by this point
-    // If there's some unknown flag we've missed, format it as hexadecimal
-    if (flags != 0) {
-      if (buffer.length() > 0) {
-        buffer.append(",");
-      }
-      buffer.append("0x").append(Integer.toHexString(flags));
-    }
-
-    return buffer.toString();
-  }
-
-
-  private void cleanup(String operation) {
     try {
-      synchronized(preparing) {
-        if (preparing.contains(session)) {
-          preparing.remove(session);
+      synchronized (preparing) {
+        if (preparing.contains(tx.session)) {
+          preparing.remove(tx.session);
         } else {
-          logger.debug("Already committed/rolledback in this transaction");
+          if (logger.isDebugEnabled()) {
+            logger.debug("Already committed/rolledback in this transaction");
+          }
         }
       }
     } finally {
       try {
         if (logger.isDebugEnabled()) {
-          logger.debug("Releasing session after " + operation + " " + session);
+          logger.debug("Releasing session after " + operation + " " + tx.session);
         }
-        session.release();
-        session = null;
+        tx.session.release();
+        tx.session = null;
       } catch (SimpleXAResourceException es) {
         logger.error("Attempt to release store failed", es);
       }
     }
   }
+
+  static class StatementStoreTxInfo extends TxInfo {
+    /** the underlying resolver-session to use */
+    public XAResolverSession session;
+
+    /** the underlying resources */
+    public SimpleXAResource[] resources;
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.Constraint;
@@ -70,8 +70,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(TripleAVLFile.class.getName());
+  private final static Logger logger = Logger.getLogger(TripleAVLFile.class);
 
   /**
    * Get line separator.

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFileUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFileUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleAVLFileUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.*;
@@ -71,8 +71,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(TripleAVLFileUnitTest.class.getName());
+  private final static Logger logger = Logger.getLogger(TripleAVLFileUnitTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleWriteThread.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleWriteThread.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/TripleWriteThread.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.LinkedList;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.statement.*;
@@ -42,8 +42,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(TripleWriteThread.class.getName());
+  private final static Logger logger = Logger.getLogger(TripleWriteThread.class);
 
   private static final int BUFFER_SIZE = 50000;
 

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.*;
@@ -78,8 +78,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(XAStatementStoreImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(XAStatementStoreImpl.class);
 
   final static boolean RELEASE_NODE_LISTENERS_ENABLED = false;
 

Modified: branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImplUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImplUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-store/java/org/mulgara/store/statement/xa/XAStatementStoreImplUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -69,8 +69,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(XAStatementStoreImplUnitTest.class.getName());
+  private final static Logger logger = Logger.getLogger(XAStatementStoreImplUnitTest.class);
 
   /**
    * start of filenames to build the graph with.

Modified: branches/mgr-61-sparql/src/jar/resolver-test/java/org/mulgara/resolver/test/TestResolverUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-test/java/org/mulgara/resolver/test/TestResolverUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-test/java/org/mulgara/resolver/test/TestResolverUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -76,8 +76,7 @@
 public class TestResolverUnitTest extends TestCase {
 
   /** Logger.  */
-  private final static Category logger =
-      Category.getInstance(TestResolverUnitTest.class.getName());
+  private final static Logger logger = Logger.getLogger(TestResolverUnitTest.class);
 
   /**
    * Test {@link Database} used to generate
@@ -132,7 +131,7 @@
     Session session = database.newSession();
 
     Variable[] varArray = new Variable[] { new Variable("a"), new Variable("b") };
-    List<Object> variables = Arrays.asList((Object[])varArray);
+    List<Variable> variables = Arrays.asList((Variable[])varArray);
 
     Answer answer = session.query(new Query(
       variables,                                                                // SELECT
@@ -179,7 +178,7 @@
     Session session = database.newSession();
 
     Variable[] varArray = new Variable[] { new Variable("a"), new Variable("c") };
-    List<Object> variables = Arrays.asList((Object[])varArray);
+    List<Variable> variables = Arrays.asList((Variable[])varArray);
 
     Answer answer = session.query(new Query(
       variables,                                                                // SELECT
@@ -224,7 +223,7 @@
     Session session = database.newSession();
 
     Variable[] varArray = new Variable[] { new Variable("a"), new Variable("b"), new Variable("c") };
-    List<Object> variables = Arrays.asList((Object[])varArray);
+    List<Variable> variables = Arrays.asList((Variable[])varArray);
 
     Answer answer = session.query(new Query(
       variables,                                                                // SELECT
@@ -275,7 +274,7 @@
     Session session = database.newSession();
 
     Variable[] varArray = new Variable[] { new Variable("a"), new Variable("b"), new Variable("c") };
-    List<Object> variables = Arrays.asList((Object[])varArray);
+    List<Variable> variables = Arrays.asList(varArray);
 
     Answer answer = session.query(new Query(
       variables,                                                                // SELECT
@@ -326,7 +325,7 @@
     Session session = database.newSession();
 
     Variable[] varArray = new Variable[] { new Variable("a"), new Variable("b"), new Variable("c") };
-    List<Object> variables = Arrays.asList((Object[])varArray);
+    List<Variable> variables = Arrays.asList(varArray);
 
 		try {
 			session.query(new Query(

Modified: branches/mgr-61-sparql/src/jar/resolver-view/java/org/mulgara/resolver/view/ViewResolverUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-view/java/org/mulgara/resolver/view/ViewResolverUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-view/java/org/mulgara/resolver/view/ViewResolverUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -607,7 +607,7 @@
 
         // Evaluate the query
         Answer answer = new ArrayAnswer(session.query(new Query(
-          (List<Object>)(List)test.selectList,  // SELECT
+          test.selectList,          // SELECT
           test.model,               // FROM
           test.query,               // WHERE
           null,                     // HAVING

Modified: branches/mgr-61-sparql/src/jar/resolver-xsd/java/org/mulgara/resolver/xsd/TestResolverSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/resolver-xsd/java/org/mulgara/resolver/xsd/TestResolverSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/resolver-xsd/java/org/mulgara/resolver/xsd/TestResolverSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -183,7 +183,14 @@
    * @return The factory to allow for creation of SPObjects
    */
   public SPObjectFactory getSPObjectFactory() {
-
     return spObjectFactory;
   }
+
+  public SPObject findSPObject(long gNode) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
+
+  public long findGNode(SPObject spObject) {
+    throw new UnsupportedOperationException("Not Implemented on test class");
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/rules/java/org/mulgara/rules/Rules.java
===================================================================
--- branches/mgr-61-sparql/src/jar/rules/java/org/mulgara/rules/Rules.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/rules/java/org/mulgara/rules/Rules.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -47,13 +47,6 @@
   static final long serialVersionUID = -4614382685160461725L;
 
   /**
-   * Set the base model for the rules.
-   *
-   * @param base The URI of the base data to apply rules to.
-   */
-  public void setBaseModel(URI base);
-
-  /**
    * Set the target model for the rules.
    *
    * @param base The URI of the target model to insert the inferences into.

Modified: branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/AbstractServer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/AbstractServer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/AbstractServer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,6 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.net.*;
-import javax.naming.*;
 
 // Third party packages
 /*
@@ -54,51 +53,27 @@
  * access to the database.
  *
  * @created 2001-09-15
- *
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
- * @version $Revision: 1.9 $
- *
- * @modified $Date: 2005/01/05 04:58:59 $
- *
- * @maintenanceAuthor $Author: newmana $
- *
- * @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
- * @copyright &copy;2001 <a href="http://www.pisoftware.com/">Plugged In
- *      Software Pty Ltd</a>
- *
+ * @copyright &copy;2001 <a href="http://www.pisoftware.com/">Plugged In Software Pty Ltd</a>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
- *
  * @see <a href="http://developer.java.sun.com/developer/JDCTechTips/2001/tt0327.html#jndi">
  *      <cite>JNDI lookup in distributed systems</cite> </a>
  */
 public abstract class AbstractServer implements ServerMBean {
 
-  /**
-   * Logger. This is named after the classname.
-   */
-  private final static Logger logger =
-      Logger.getLogger(AbstractServer.class.getName());
+  /** Logger. This is named after the classname. */
+  private final static Logger logger = Logger.getLogger(AbstractServer.class.getName());
 
-  /**
-   * The class name of the {@link SessionFactory} implementation.
-   */
+  /** The class name of the {@link SessionFactory} implementation. */
   private String providerClassName;
 
-  /**
-   * The directory where the server can write files.
-   */
+  /** The directory where the server can write files. */
   private File dir;
 
-  /**
-   * The directory where the server can write temporary files.
-   */
+  /** The directory where the server can write temporary files. */
   private File tempdir;
 
-  /**
-   * The server URI.
-   */
+  /** The server URI. */
   private URI uri;
 
   /**
@@ -106,81 +81,67 @@
    */
   private int portNumber = -1;
 
-  /**
-   * The hostname of the server.
-   */
+  /** The hostname of the server. */
   protected String hostname = null;
 
-  /**
-   * State.
-   */
+  /** State. */
   private int state = UNINITIALIZED;
 
-  /**
-   * The server object.
-   */
+  /** The server object. */
   private SessionFactory sessionFactory;
 
   /** The session factory config object */
   private MulgaraConfig sessionConfig;
 
-  /**
-   * ZeroConf server.
-   */
-  /*
-  private JmDNS jmdns;
-  */
+  // /** ZeroConf server. */
+  // private JmDNS jmdns;
 
   /**
    * Returns the hostname of the server.
-   *
    * @return The Hostname value
    */
   public String getHostname() {
-
     return hostname;
   }
 
+  /**
+   * Sets the server port.
+   * @param newPortNumber The new port to bind to.
+   */
   public void setPortNumber(int newPortNumber) {
-
+    // Prevent the port from being changed while the server is up
+    if (this.getState() == STARTED) {
+      throw new IllegalStateException("Can't change server port without first stopping the server");
+    }
     portNumber = newPortNumber;
+    if (uri != null && uri.getPort() == -1) uri = updateUriPort(uri);
+    // else expect URI to be updated now
   }
 
   /**
    * Returns the port number that the server is to bind to.
-   *
    * @return the port number value.
    */
   public int getPortNumber() {
-
     return portNumber;
   }
 
   /**
    * Sets the hostname of the server.
-   *
-   * @param newHostname  the hostname of the server, if <code>null</code>
-   *     <code>localhost</code> will be used
-   * @throws IllegalStateException if the service is started or if the
-   *      underlying session factory already has a fixed hostname
+   * @param newHostname  the hostname of the server, if <code>null</code> <code>localhost</code> will be used
+   * @throws IllegalStateException if the service is started or if the underlying session factory already has a fixed hostname
    */
   public void setHostname(String newHostname) {
-
     // Prevent the hostname from being changed while the server is up
     if (this.getState() == STARTED) {
-
-      throw new IllegalStateException(
-          "Can't change hostname without first stopping the server");
+      throw new IllegalStateException("Can't change hostname without first stopping the server");
     }
 
     // Reset the field
-    if (hostname == null) {
-
+    if (newHostname == null) {
       this.hostname = "localhost";
       logger.warn("Hostname supplied is null, defaulting to localhost");
-    }
-    else {
-
+    } else {
       hostname = newHostname;
     }
   }
@@ -191,13 +152,11 @@
    * @param dir The new Dir value
    */
   public void setDir(File dir) {
-
     this.dir = dir;
   }
 
   /**
    * Set the temporary database directory.
-   *
    * @param tempdir The new Dir value
    */
   public void setTempDir(File tempdir) {
@@ -207,11 +166,9 @@
 
   /**
    * Set the database provider classname.
-   *
    * @param providerClassName The new ProviderClassName value
    */
   public void setProviderClassName(String providerClassName) {
-
     this.providerClassName = providerClassName;
   }
 
@@ -221,62 +178,50 @@
 
   /**
    * Read the server state.
-   *
    * @return The current server state.
    */
   public int getState() {
-
     return state;
   }
 
   /**
    * Read the database directory.
-   *
    * @return The Dir value
    */
   public File getDir() {
-
     return dir;
   }
 
   /**
    * Read the temporary database directory.
-   *
    * @return The tempdir value
    */
   public File getTempDir() {
-
     return tempdir;
   }
 
   /**
    * Read the database provider classname.
-   *
    * @return The ProviderClassName value
    */
   public String getProviderClassName() {
-
     return providerClassName;
   }
 
   /**
    * Read the database URI.
-   *
    * @return The URI value
    */
   public URI getURI() {
-
     return uri;
   }
 
   /**
    * Allow access by subclasses to the session factory.
-   *
-   * @return <code>null</code> in the {@link #UNINITIALIZED} state, the {@link
-   *      SessionFactory} instance otherwise
+   * @return <code>null</code> in the {@link #UNINITIALIZED} state, the {@link SessionFactory}
+   *         instance otherwise
    */
   public SessionFactory getSessionFactory() {
-
     return sessionFactory;
   }
 
@@ -289,91 +234,61 @@
    * database. Initialization requires a non-null <var>name</var> and <var>
    * providerClassName</var> .
    *
-   * @throws ClassNotFoundException if the <var>providerClassName</var> isn't in
-   *      the classpath
-   * @throws IOException if the persistence directory doesn't exist and can't be
-   *      created
-   * @throws NoSuchMethodException if the <var>providerClassName</var> doesn't
-   *      have a constructor with the correct signature
-   * @throws IllegalAccessException EXCEPTION TO DO
-   * @throws InstantiationException EXCEPTION TO DO
-   * @throws InvocationTargetException EXCEPTION TO DO
+   * @throws ClassNotFoundException if the <var>providerClassName</var> isn't in the classpath
+   * @throws IOException if the persistence directory doesn't exist and can't be created
+   * @throws NoSuchMethodException if the <var>providerClassName</var> doesn't have a
+   *         constructor with the correct signature
+   * @throws IllegalAccessException There was a permissions error during setup.
+   * @throws InstantiationException The {@link SessionFactory} could not be created.
+   * @throws InvocationTargetException  The {@link SessionFactory} had an error during construction.
    */
   public final void init() throws ClassNotFoundException,
       IllegalAccessException, InstantiationException, InvocationTargetException,
       IOException, NoSuchMethodException {
 
-    // Create the server
-    if (logger.isInfoEnabled()) {
-      logger.info("Create server");
-    }
+    if (logger.isInfoEnabled()) logger.info("Create server");
 
     // Validate state
-    if (dir == null) {
+    if (dir == null) throw new IllegalStateException("Must set \"dir\" property");
+    if (tempdir == null) throw new IllegalStateException("Must set \"tempdir\" property");
+    if (providerClassName == null) throw new IllegalStateException("Must set \"providerClassName\" property");
 
-      throw new IllegalStateException("Must set \"dir\" property");
-    }
-
-    if (tempdir == null) {
-
-      throw new IllegalStateException("Must set \"tempdir\" property");
-    }
-
-    if (providerClassName == null) {
-
-      throw new IllegalStateException("Must set \"providerClassName\" property");
-    }
-
     // Create the directory if necessary
-    if (!dir.exists()) {
+    if (!dir.exists()) dir.mkdir();
 
-      dir.mkdir();
-    }
-
     // create the temporary directory
     tempdir.mkdirs();
 
     // Log provider class name
-    if (logger.isInfoEnabled()) {
-      logger.info("Provider class is " + providerClassName);
-    }
+    if (logger.isInfoEnabled()) logger.info("Provider class is " + providerClassName);
 
     if (sessionConfig == null) {
-
       // Create the session factory using the two parameter constructor if we
       // have no configuration
       sessionFactory =
-          (SessionFactory) Class.forName(providerClassName)
-          .getConstructor(new Class[] {
-                          URI.class, File.class})
-          .newInstance(new Object[] {
-                       getURI(), dir});
+          (SessionFactory)Class.forName(providerClassName)
+          .getConstructor(new Class[] {URI.class, File.class})
+          .newInstance(new Object[] {getURI(), dir});
     } else {
-
       // Create the session factory using the three parameter constructor if we
       // have a configuration to use
       sessionFactory =
-          (SessionFactory) Class.forName(providerClassName)
-          .getConstructor(new Class[] {
-                          URI.class, File.class, MulgaraConfig.class})
-          .newInstance(new Object[] {
-                       getURI(), dir, sessionConfig});
+          (SessionFactory)Class.forName(providerClassName)
+          .getConstructor(new Class[] {URI.class, File.class, MulgaraConfig.class})
+          .newInstance(new Object[] {getURI(), dir, sessionConfig});
     }
 
-    //assert sessionFactory != null;
     state = STOPPED;
 
     // Log successful creation
-    if (logger.isInfoEnabled()) {
-      logger.info("Created server");
-    }
+    if (logger.isInfoEnabled()) logger.info("Created server");
   }
 
   /**
    * Make the server available over the network. If successful the new state
    * should be {@link #STARTED}.
-   *
-   * @throws Exception EXCEPTION TO DO
+   * @throws IllegalStateException The service is not configured, or is already running.
+   * @throws Exception A service specific error occurred during startup.
    */
   public final void start() throws Exception {
 
@@ -389,42 +304,35 @@
         throw new IllegalStateException("Already started");
     }
 
-    //assert state == STOPPED
+    assert state == STOPPED;
+
     // Invariant tests for the STOPPED state
-    if (sessionFactory == null) {
+    if (sessionFactory == null) throw new AssertionError("Null \"sessionFactory\" parameter");
 
-      throw new AssertionError("Null \"sessionFactory\" parameter");
-    }
-
     startService();
 
-    /*
     // Start advertising the service via ZeroConf
-    if (jmdns == null) {
-      try {
-        logger.info("Starting ZeroConf server");
-        jmdns = new JmDNS(InetAddress.getLocalHost());
-        logger.info("Started ZeroConf server");
+    // if (jmdns == null) {
+    //   try {
+    //     logger.info("Starting ZeroConf server");
+    //     jmdns = new JmDNS(InetAddress.getLocalHost());
+    //     logger.info("Started ZeroConf server");
 
-        String type = "_rmi._tcp.local";
-        logger.info(
-          "Registering as itql."+type+" on port 1099 with ZeroConf server"
-        );
-        jmdns.registerService(new ServiceInfo(
-          type,           // type
-          "itql."+type,   // name
-          1099,           // port
-          0,              // weight
-          0,              // priority
-          "path=server1"  // text
-        ));
-        logger.info("Registered with ZeroConf server");
-      }
-      catch (IOException e) {
-        logger.warn("Couldn't start ZeroConf server", e);
-      }
-    }
-    */
+    //     String type = "_rmi._tcp.local";
+    //     logger.info("Registering as itql."+type+" on port 1099 with ZeroConf server");
+    //     jmdns.registerService(new ServiceInfo(
+    //       type,           // type
+    //       "itql."+type,   // name
+    //       1099,           // port
+    //       0,              // weight
+    //       0,              // priority
+    //       "path=server1"  // text
+    //     ));
+    //     logger.info("Registered with ZeroConf server");
+    //   } catch (IOException e) {
+    //     logger.warn("Couldn't start ZeroConf server", e);
+    //   }
+    // }
 
     state = STARTED;
     logger.info("Started");
@@ -432,27 +340,21 @@
 
   /**
    * Make the server unavailable over the network. If successful the new state
-   * should be {@link #STOPPED}.
-   *
-   * @throws Exception EXCEPTION TO DO
+   * will be {@link #STOPPED}.
+   * @throws IllegalStateException If the server is not running
+   * @throws Exception There was a service specific error in shutting down.
    */
   public final void stop() throws Exception {
 
     logger.info("Shutting down");
 
     // Validate state
-    if (state != STARTED) {
+    if (state != STARTED) throw new IllegalStateException("Server is not started");
 
-      throw new IllegalStateException("Server is not started");
-    }
-
-    //assert state == STARTED;
-    /*
-    if (jmdns != null) {
-      logger.info("Unregistering from ZeroConf server");
-      jmdns.unregisterAllServices();
-    }
-    */
+    // if (jmdns != null) {
+    //   logger.info("Unregistering from ZeroConf server");
+    //   jmdns.unregisterAllServices();
+    // }
     stopService();
     state = STOPPED;
     logger.info("Shut down");
@@ -460,24 +362,19 @@
 
   /**
    * Destroy the server.
-   *
    */
   public final void destroy() {
-
     logger.info("Destroying");
 
     try {
       sessionFactory.close();
+    } catch (QueryException e) {
+      logger.warn("Couldn't close server " + uri, e);
     }
-    catch (QueryException e) {
-      logger.warn("Couldn't close server "+uri, e);
-    }
 
-    /*
-    if (jmdns != null) {
-      jmdns.unregisterAllServices();
-    }
-    */
+    // if (jmdns != null) {
+    //   jmdns.unregisterAllServices();
+    // }
     sessionFactory = null;
     state = UNINITIALIZED;
     logger.info("Destroyed");
@@ -487,58 +384,75 @@
    * Set the database URI. Implementing subclasses would typically derive a URI
    * from other properties and call this method whenever those properties are
    * modified.
-   *
    * @param uri the desired server URI, or <code>null</code>
    * @throws IllegalStateException if the service is started or if the
    *      underlying session factory already has a fixed URI
    */
   protected void setURI(URI uri) {
-
     // Prevent the URI from being changed while the server is up
-    if (state == STARTED) {
-
-      throw new IllegalStateException(
-          "Can't change URI without first stopping the server");
-    }
-
-    // Reset the field
+    if (state == STARTED) throw new IllegalStateException("Can't change URI without first stopping the server");
     this.uri = uri;
   }
 
   /**
- * Retrieves the configuration used when initialising a session factory.
- *
- * @return The configuration used when initialising a session factory
- */
-public MulgaraConfig getConfig() {
+   * Retrieves the configuration used when initialising a session factory.
+   * @return The configuration used when initialising a session factory
+   */
+  public MulgaraConfig getConfig() {
+    return sessionConfig;
+  }
+  
+  /**
+   * Sets the configuration to be used when bringing up a session factory.
+   * @param config The configuration to be used when bringing up a sessionfactory
+   */
+  public void setConfig(MulgaraConfig config) {
+    // Store the new configuration item
+    sessionConfig = config;
+  }
 
-  return sessionConfig;
-}
+  /**
+   * Utility to check that the URI has the port set correctly.
+   * If the port is not specified in the URI and this server instance has a non-default port,
+   * then the URI is updated to the new port with a warning. If the port is specified and it does
+   * not match the server port, then an IllegalArgumentException is thrown.
+   * @param u The port to check.
+   * @return IllegalArgumentException If the port specified in the URI is different to the
+   *         port in use by this server.
+   */
+  protected URI updateUriPort(URI u) {
+    int port = u.getPort();
+    if (port == -1) {
+      if (portNumber != getDefaultPort()) {
+        try {
+          u = new URI(u.getScheme(), u.getUserInfo(), u.getHost(), portNumber, u.getPath(), u.getQuery(), u.getFragment());
+        } catch (URISyntaxException e) {
+          throw new IllegalArgumentException("URI has unexpected structure: " + u);
+        }
+        logger.warn("Setting server URI without configured port.  Changing to: ");
+      }
+    } else {
+      if (port != portNumber) throw new IllegalArgumentException("Server URI must match the port <" + uri +"> port:" + portNumber);
+    }
+    return u;
+  }
 
-/**
- * Sets the configuration to be used when bringing up a session factory.
- *
- * @param config The configuration to be used when bringing up a session
- *               factory
- */
-public void setConfig(MulgaraConfig config) {
+  /**
+   * Indicates the default port used by this server's protocol. This is a static final value
+   * and should correspond to the scheme in the URI (e.g. http => port 80).
+   * @return The default port for this server.
+   */
+  protected abstract int getDefaultPort();
 
-  // Store the new configuration item
-  sessionConfig = config;
-}
-
-
   /**
-   * METHOD TO DO
-   *
-   * @throws Exception EXCEPTION TO DO
+   * Start the service that this server provides.
+   * @throws Exception Indicating an error in server startup.
    */
   protected abstract void startService() throws Exception;
 
   /**
-   * METHOD TO DO
-   *
-   * @throws Exception EXCEPTION TO DO
+   * Stop the service that this server provides.
+   * @throws Exception Indicating an error in server shutdown.
    */
   protected abstract void stopService() throws Exception;
 }

Modified: branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/EmbeddedMulgaraOptionParser.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/EmbeddedMulgaraOptionParser.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server/java/org/mulgara/server/EmbeddedMulgaraOptionParser.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import jargs.gnu.CmdLineParser;
 
 // third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Command line option parser for the Mulgara server.
@@ -126,8 +126,7 @@
   /**
    * the category to log to
    */
-  private final static Category log =
-      Category.getInstance(EmbeddedMulgaraOptionParser.class.getName());
+  private final static Logger log = Logger.getLogger(EmbeddedMulgaraOptionParser.class);
 
   //
   // members

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPAnswer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPAnswer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPAnswer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;             // Apache Log4J
+import org.apache.log4j.Logger;             // Apache Log4J
 import org.beepcore.beep.core.BEEPException;  // BEEP
 import org.beepcore.beep.core.Channel;
 import org.beepcore.beep.core.Message;
@@ -62,8 +62,7 @@
   /**
   * Logger.
   */
-  private static final Category logger =
-    Category.getInstance(BEEPAnswer.class.getName());
+  private static final Logger logger = Logger.getLogger(BEEPAnswer.class);
 
   /**
   * The BEEP channel to close once this instance is closed.

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPServer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPServer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPServer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -40,8 +40,6 @@
 
 // Locally written packages
 import org.mulgara.server.AbstractServer;
-import org.mulgara.server.Session;
-import org.mulgara.server.SessionFactory;
 
 /**
 * Mulgara server using a BEEP-based ITQL application protocol.
@@ -49,59 +47,36 @@
 * @created 2004-03-21
 * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
 * @author <a href="http://staff.pisoftware.com/david">David Makepeace</a>
-* @version $Revision: 1.9 $
-* @modified $Date: 2005/01/05 04:59:00 $ by $Author: newmana $
-* @company <a href="mailto:info at PIsoftware.com">Plugged In Software</a>
-* @copyright &copy;2004 <a href="http://www.pisoftware.com/">Plugged In
-*      Software Pty Ltd</a>
+* @copyright &copy;2004 <a href="http://www.pisoftware.com/">Plugged In Software Pty Ltd</a>
 * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
 */
-public class BEEPServer extends AbstractServer
-{
-  /**
-  * Logger.
-  */
-  private static final Logger logger =
-    Logger.getLogger(BEEPServer.class.getName());
+public class BEEPServer extends AbstractServer {
+  /** Logger. */
+  private static final Logger logger = Logger.getLogger(BEEPServer.class.getName());
 
-  /**
-  * The server port.
-  *
-  * BEEP's default port is 10288.
-  */
-  final int port = 10288;
+  /** BEEP's default port is 10288. */
+  static final int DEFAULT_PORT = 10228;
 
-  /**
-  * Socket accepting session requests from clients.
-  */
+  /** The server port. BEEP's default port is 10288. */
+  final int port = DEFAULT_PORT;
+
+  /** Socket accepting session requests from clients. */
   private ServerSocket serverSocket = null;
 
-  /**
-  * The collection of supported BEEP profiles.
-  *
-  * We add only the ITQL profile.
-  */
+  /** The collection of supported BEEP profiles. We add only the ITQL profile. */
   private ProfileRegistry profileRegistry = null;
 
   /**
-  * The thread which accepts session requests on the {@link #serverSocket}.
-  *
-  * This field is <code>null</code> whenever the server isn't {@link #STARTED}.
-  */
+   * The thread which accepts session requests on the {@link #serverSocket}.
+   * This field is <code>null</code> whenever the server isn't {@link #STARTED}.
+   */
   private Thread thread;
 
-  //
-  // Constructor
-  //
-
   /**
-  * Create a BEEP server MBean.
-  *
-  * @throws UnknownHostException  if the DNS name of the local host can't be
-  *                               determined
-  */
-  public BEEPServer() throws UnknownHostException
-  {
+   * Create a BEEP server MBean.
+   * @throws UnknownHostException if the DNS name of the local host can't be determined
+   */
+  public BEEPServer() throws UnknownHostException {
     // Generate server URI
     try {
       setURI(new URI("beep",                                    // scheme
@@ -111,8 +86,7 @@
                      null,                                      // path
                      null,                                      // query
                      null));
-    }
-    catch (URISyntaxException e) {
+    } catch (URISyntaxException e) {
       throw new Error("Bad generated URI", e);
     }
   }
@@ -122,19 +96,15 @@
   //
 
   /**
-  * Sets the hostname of the server.
-  *
-  * @param hostname  the hostname of the server; if <code>null</code>, the
-  *   local host name of the machine will be used if it can be found,
-  *   otherwise <code>localhost</code> will be used.
-  */
-  public void setHostname(String hostname)
-  {
+   * Sets the hostname of the server.
+   * @param hostname  the hostname of the server; if <code>null</code>, the
+   *   local host name of the machine will be used if it can be found,
+   *   otherwise <code>localhost</code> will be used.
+   */
+  public void setHostname(String hostname) {
     // prevent the hostname from being changed while the server is up
     if (this.getState() == STARTED) {
-      throw new IllegalStateException(
-        "Can't change hostname without first stopping the server"
-      );
+      throw new IllegalStateException("Can't change hostname without first stopping the server");
     }
 
     // get the hostname
@@ -142,8 +112,7 @@
       // try to use the local host name
       try {
         hostname = InetAddress.getLocalHost().getHostName();
-      }
-      catch (Exception e) {
+      } catch (Exception e) {
         logger.warn("Problem getting host name! - using localhost");
         hostname = "localhost";
       }
@@ -161,8 +130,7 @@
                      null,                            // path
                      null,                            // query
                      null));
-    }
-    catch (URISyntaxException e) {
+    } catch (URISyntaxException e) {
       throw new Error("Bad generated URI", e);
     }
   }
@@ -172,22 +140,18 @@
   //
 
   /**
-  * Returns the hostname of the server.
-  *
-  * @return the hostname of the server
-  */
-  public String getHostname()
-  {
+   * Returns the hostname of the server.
+   * @return the hostname of the server
+   */
+  public String getHostname() {
     return hostname;
   }
 
   /**
-  * Start the server.
-  *
-  * @throws Exception EXCEPTION TO DO
-  */
-  protected void startService() throws Exception
-  {
+   * Start the server.
+   * @throws Exception EXCEPTION TO DO
+   */
+  protected void startService() throws Exception {
     if (thread == null) {
       serverSocket = new ServerSocket(port);
 
@@ -210,28 +174,22 @@
       );
 
       // Launch the server thread
-      thread = new Thread()
-      {
-        public void run()
-        {
+      thread = new Thread() {
+        public void run() {
           try {
             while (true) {
               Socket socket = serverSocket.accept();
               TCPSession.createListener(socket, profileRegistry);
             }
-          }
-          catch (InterruptedIOException ex) {
+          } catch (InterruptedIOException ex) {
             // Stop the thread.
-          }
-          catch (Exception ex) {
+          } catch (Exception ex) {
             logger.error("Exception in ServerThread: " + ex);
-          }
-          finally {
+          } finally {
             if (serverSocket != null) {
               try {
                 serverSocket.close();
-              }
-              catch (IOException ex) {
+              } catch (IOException ex) {
                 // ignore failures
               }
             }
@@ -246,12 +204,10 @@
   }
 
   /**
-  * Stop the server.
-  *
-  * @throws Exception EXCEPTION TO DO
-  */
-  protected void stopService() throws Exception
-  {
+   * Stop the server.
+   * @throws IOException I/O error closing the server socket.
+   */
+  protected void stopService() throws IOException {
     if (thread != null) {
       thread.interrupt();
       thread          = null;
@@ -261,10 +217,17 @@
     if (serverSocket != null) {
       try {
         serverSocket.close();
-      }
-      finally {
+      } finally {
         serverSocket = null;
       }
     }
   }
+
+  /**
+   * Informs the base class what the default port for this protocol is.
+   * @see org.mulgara.server.AbstractServer#getDefaultPort()
+   */
+  protected int getDefaultPort() {
+    return DEFAULT_PORT;
+  }
 }

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/BEEPSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *    XAResource addition copyright 2008 The Topaz Foundation
  *
  * [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
@@ -32,9 +33,10 @@
 import java.net.*;
 import java.rmi.RemoteException;
 import java.util.*;
+import javax.transaction.xa.XAResource;
 
 // Third party packages
-import org.apache.log4j.Category; // Apache Log4J
+import org.apache.log4j.Logger; // Apache Log4J
 import org.beepcore.beep.core.BEEPException; // BEEP
 import org.beepcore.beep.core.ByteOutputDataStream;
 import org.beepcore.beep.core.Channel;
@@ -91,8 +93,7 @@
    *
    * This is named after the class.
    */
-  private static final Category logger =
-      Category.getInstance(BEEPSession.class.getName());
+  private static final Logger logger = Logger.getLogger(BEEPSession.class);
 
   /**
    * The wrapped BEEP session.
@@ -534,8 +535,15 @@
  /**
   * {@inheritDoc}
   */
- public void applyRules(RulesRef rules) throws RulesException {
+ public void applyRules(RulesRef rules) {
    throw new UnsupportedOperationException("This operation is only supported on local sessions.");
  }
 
+ public XAResource getXAResource() throws QueryException {
+   throw new QueryException("External transactions not implemented under Beep");
+ }
+
+ public XAResource getReadOnlyXAResource() throws QueryException {
+   throw new QueryException("External transactions not implemented under Beep");
+ }
 }

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandProfile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandProfile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandProfile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -4,7 +4,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;    // Log4J
+import org.apache.log4j.Logger;    // Log4J
 import org.beepcore.beep.core.*;     // BEEP
 import org.beepcore.beep.profile.*;
 
@@ -30,7 +30,7 @@
   /**
   * Logger.
   */
-  private final Category logger = Category.getInstance(getClass().getName());
+  private final static Logger logger = Logger.getLogger(CommandProfile.class);
 
   /**
   * The Mulgara session wrapped by this BEEP session.

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandRequestHandler.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandRequestHandler.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/CommandRequestHandler.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -5,7 +5,7 @@
 import java.util.StringTokenizer;
 
 // Third party packages
-import org.apache.log4j.Category;    // Log4J
+import org.apache.log4j.Logger;    // Log4J
 import org.beepcore.beep.core.*;     // BEEP
 
 // Local packages
@@ -22,7 +22,7 @@
   /**
   * Logger.
   */
-  private final Category logger = Category.getInstance(getClass().getName());
+  private final static Logger logger = Logger.getLogger(CommandRequestHandler.class);
 
   /**
   * The Mulgara session wrapped by this BEEP session.

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryProfile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryProfile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryProfile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -4,7 +4,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;    // Log4J
+import org.apache.log4j.Logger;      // Log4J
 import org.beepcore.beep.core.*;     // BEEP
 import org.beepcore.beep.profile.*;
 
@@ -30,7 +30,7 @@
   /**
   * Logger.
   */
-  private final Category logger = Category.getInstance(getClass().getName());
+  private final static Logger logger = Logger.getLogger(QueryProfile.class);
 
   /**
   * The Mulgara session wrapped by this BEEP session.

Modified: branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryRequestHandler.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryRequestHandler.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-beep/java/org/mulgara/server/beep/QueryRequestHandler.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -4,7 +4,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;    // Log4J
+import org.apache.log4j.Logger;    // Log4J
 import org.beepcore.beep.core.*;     // BEEP
 
 // Local packages
@@ -22,9 +22,9 @@
 public class QueryRequestHandler implements RequestHandler
 {
   /**
-  * Logger.
-  */
-  private final Category logger = Category.getInstance(getClass().getName());
+   * Logger.
+   */
+  private final static Logger logger = Logger.getLogger(QueryRequestHandler.class);
 
   /**
   * The Mulgara session wrapped by this BEEP session.

Modified: branches/mgr-61-sparql/src/jar/server-http/build.xml
===================================================================
--- branches/mgr-61-sparql/src/jar/server-http/build.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-http/build.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -150,7 +150,7 @@
     <manifest file="${obj.dir}/META-INF/MANIFEST_Mulgara_HTTP_BOOTSTRAP.MF">
 
       <attribute name="Main-Class" value="org.mulgara.util.Bootstrap"/>
-      <attribute name="Embedded-Jar" value="lib/${driver.jar}, lib/${query.jar},lib/${itql.jar}, lib/${rules.jar}, lib/${server.jar}, lib/${util.jar}, lib/${config.jar}, lib/activation-1.0.2.jar, lib/icu4j.jar, lib/jena-2.1.jar,lib/antlr.jar, lib/${commons-logging.jar}, lib/log4j-1.2.8.jar, lib/mail-1.3.jar, lib/${jetty.jar},lib/${jetty.plus.jar}, lib/${jasper.runtime.jar}, lib/${servlet.jar}, lib/jargs-0.2.jar,lib/castor-0.9.3.9-xml.jar, lib/xercesImpl.jar, lib/xmlParserAPIs.jar, lib/${jrdf.jar},lib/jakarta-oro-2.0.5.jar, lib/${emory-util.jar}"/>
+      <attribute name="Embedded-Jar" value="lib/${driver.jar}, lib/${query.jar},lib/${itql.jar}, lib/${rules.jar}, lib/${server.jar}, lib/${util.jar}, lib/${config.jar}, lib/activation-1.0.2.jar, lib/icu4j.jar, lib/jena-2.1.jar,lib/antlr.jar, lib/${commons-logging.jar}, lib/log4j-1.2.15.jar, lib/mail-1.3.jar, lib/${jetty.jar},lib/${jetty.plus.jar}, lib/${jasper.runtime.jar}, lib/${servlet.jar}, lib/jargs-0.2.jar,lib/castor-0.9.3.9-xml.jar, lib/xercesImpl.jar, lib/xmlParserAPIs.jar, lib/${jrdf.jar},lib/jakarta-oro-2.0.5.jar, lib/${emory-util.jar}"/>
       <attribute name="Embedded-Main-Class" value="org.mulgara.server.EmbeddedMulgaraHttpServer"/>
     </manifest>
 

Modified: branches/mgr-61-sparql/src/jar/server-http/java/org/mulgara/server/http/HttpSessionFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-http/java/org/mulgara/server/http/HttpSessionFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-http/java/org/mulgara/server/http/HttpSessionFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -185,8 +185,7 @@
      * Logger.
      *
      */
-    final static Category logger =
-        Category.getInstance(InvocationHandlerImpl.class.getName());
+    final static Logger logger = Logger.getLogger(InvocationHandlerImpl.class);
 
     private URL serverURL;
 

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -45,21 +45,9 @@
 /**
  * Contains a serializable page of answers retrieved from an {@link org.mulgara.query.Answer} object.
  *
- * @author <a href="http://staff.pisoftware.com/pag">Paul Gearon</a>
- *
+ * @author <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
  * @created 2004-03-26
- *
- * @version $Revision: 1.10 $
- *
- * @modified $Date: 2005/01/27 11:57:08 $
- *
- * @maintenanceAuthor $Author: newmana $
- *
- * @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
- * @copyright &copy; 2001-2003 <A href="http://www.PIsoftware.com/">Plugged In
- *      Software Pty Ltd</A>
- *
+ * @copyright &copy; 2001-2003 <A href="http://www.PIsoftware.com/">Plugged In Software Pty Ltd</A>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 public class AnswerPageImpl implements AnswerPage, Externalizable {
@@ -81,17 +69,14 @@
   /** Size of compression/decompression buffer */
   static final int CLIENT_BUFFER_SIZE = 4096;
 
-  /**
-   * The logging category to log to.
-   */
+  /** The logging category to log to. */
   private final static Logger log = Logger.getLogger(AnswerPageImpl.class.getName());
 
-
   /** The number of rows used in this page */
   private int pageSize = 0;
 
   /** The data held in the page. */
-  private List rows;
+  private List<Object[]> rows;
 
   /** The current row number. */
   private int currentRow;
@@ -105,6 +90,7 @@
   public AnswerPageImpl() throws TuplesException {
     // nothing
   }
+
   /**
    * Main Constructor.  Copies rows from an Answer into internal serializable data.
    * @param answer The Answer to get data from.  This Answer gets moved on by up to pageSize rows.
@@ -112,7 +98,7 @@
    * @throws TuplesException Can be thrown while accessing the answer parameter.
    */
   public AnswerPageImpl(Answer answer, int pageSize) throws TuplesException {
-    rows = new ArrayList(pageSize);
+    rows = new ArrayList<Object[]>(pageSize);
 
     int width = answer.getNumberOfVariables();
 
@@ -212,7 +198,6 @@
 
   /**
    * Indicates that this is the last page constructable for the current answer.
-   *
    * @return true if there are no more pages after this one.
    */
   public boolean isLastPage() {
@@ -221,20 +206,16 @@
 
   /**
    * Reads the entire page to the input stream, decompressing if requested.
-   *
    * @param in The data stream to read from.
    */
-  public void readExternal(ObjectInput in)
-      throws IOException, ClassNotFoundException {
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
 
     // read the flag to see if the remaining stream is compressed
     boolean compression = in.readBoolean();
 
     // determine the uncompressed size of a compressed stream
     int uncompressedSize = 0;
-    if (compression) {
-      uncompressedSize = in.readInt();
-    }
+    if (compression) uncompressedSize = in.readInt();
 
     // read in the bytes which make up the rest of the object
     byte[] byteArray = (byte[])in.readObject();
@@ -293,7 +274,6 @@
 
   /**
    * Writes the entire page to the output stream, compressing if requested.
-   *
    * @param out The data stream to write to.
    */
   public void writeExternal(ObjectOutput out) throws IOException {
@@ -344,7 +324,6 @@
 
   /**
    * Helper method for writeExternal to write the rows object.
-   *
    * @param output The object output stream to write rows into.
    */
   protected void writeRows(ObjectOutputStream output) throws IOException {
@@ -353,13 +332,11 @@
       output.writeInt(rows.size());
 
       // The data in each row
-      Iterator ri = rows.iterator();
+      Iterator<Object[]> ri = rows.iterator();
       while (ri.hasNext()) {
-        Object[] line = (Object[])ri.next();
+        Object[] line = ri.next();
         // now write each element in the line
-        for (int c = 0; c < columnNames.length; c++) {
-          output.writeObject(line[c]);
-        }
+        for (int c = 0; c < columnNames.length; c++) output.writeObject(line[c]);
       }
     } catch (IOException ei) {
       log.warn("IOException thrown", ei);
@@ -379,7 +356,7 @@
   protected void readRows(ObjectInputStream input) throws IOException, ClassNotFoundException {
     // the number of rows
     int rowCount = input.readInt();
-    rows = new ArrayList(pageSize);
+    rows = new ArrayList<Object[]>(pageSize);
 
     // iterate over each row and add
     for (int r = 0; r < rowCount; r++) {
@@ -391,14 +368,12 @@
       // add the row to the page
       rows.add(line);
     }
-
   }
 
 
   /**
    * Helper method for writeExternal to test if compression is needed,
    * and compresses the data if applicable.
-   *
    * @param outStream The output stream to set the compression on.
    * @param data The data to compress for the stream.
    * @return The new data for the stream.
@@ -407,9 +382,7 @@
     // test if compression should be used
     int clevel = Integer.getInteger(COMPRESSION_LEVEL, 1).intValue();
     if (clevel > 0) {
-      if (clevel > Deflater.BEST_COMPRESSION) {
-        clevel = Deflater.BEST_COMPRESSION;
-      }
+      if (clevel > Deflater.BEST_COMPRESSION) clevel = Deflater.BEST_COMPRESSION;
       // store the length of the buffer
       int datalength = data.length;
 

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImplUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImplUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerPageImplUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import java.sql.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.*;
@@ -67,7 +67,7 @@
   /**
    * Logger.
    */
-  private Category logger = Category.getInstance(AnswerPageImplUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(AnswerPageImplUnitTest.class);
 
   /**
    * Constructs a new answer test with the given name.

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerWrapperRemoteAnswerSerialised.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerWrapperRemoteAnswerSerialised.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/AnswerWrapperRemoteAnswerSerialised.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,6 @@
 import java.io.Serializable;
 
 // Third party packages
-import org.apache.log4j.Category;
 import org.mulgara.query.Answer;
 import org.mulgara.query.TuplesException;
 import org.mulgara.query.Variable;

Copied: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/Handler.java (from rev 722, trunk/src/jar/server-rmi/java/org/mulgara/server/rmi/Handler.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/Handler.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/Handler.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,41 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.server.rmi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * This Handler permits URLs with an RMI scheme to be created. It also refers an
+ * {@link #openConnection(URL)} request to the {@link RmiURLConnection} class.
+ *
+ * @created Mar 28, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class Handler extends URLStreamHandler {
+
+  /**
+   * @see java.net.URLStreamHandler#openConnection(java.net.URL)
+   */
+  @Override
+  protected URLConnection openConnection(URL u) throws IOException {
+    URLConnection connection = new RmiURLConnection(u);
+    connection.connect();
+    return connection;
+  }
+
+}

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/PagedRemoteAnswer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/PagedRemoteAnswer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/PagedRemoteAnswer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,6 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
 import org.mulgara.query.TuplesException;
 import org.mulgara.query.Variable;
 import org.mulgara.util.MulgaraResultSet;

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteAnswer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteAnswer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteAnswer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,6 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
 import org.mulgara.query.TuplesException;
 import org.mulgara.query.Variable;
 import org.mulgara.util.MulgaraResultSet;

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *   XAResource access copyright 2007 The Topaz Foundation.
  *
  * [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
@@ -33,20 +34,13 @@
 import java.util.*;
 import java.net.*;
 
-// JRDF
-import org.jrdf.graph.*;
-
-// emory util package
-import edu.emory.mathcs.util.remote.io.*;
-
 // Locally written packages
-import org.mulgara.query.Answer;
+import org.jrdf.graph.Triple;
 import org.mulgara.query.ModelExpression;
 import org.mulgara.query.Query;
 import org.mulgara.query.QueryException;
 import org.mulgara.rules.InitializerException;
 import org.mulgara.rules.Rules;  // Required only for Javadoc
-import org.mulgara.rules.RulesException;
 import org.mulgara.rules.RulesRef;
 
 
@@ -80,7 +74,7 @@
    * @throws QueryException if the insert cannot be completed.
    * @throws RemoteException EXCEPTION TO DO
    */
-  public void insert(URI modelURI, Set statements) throws QueryException,
+  public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException,
       RemoteException;
 
   /**
@@ -102,7 +96,7 @@
    * @throws QueryException if the deletion cannot be completed.
    * @throws RemoteException EXCEPTION TO DO
    */
-  public void delete(URI modelURI, Set statements) throws QueryException,
+  public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException,
       RemoteException;
 
   /**
@@ -259,13 +253,14 @@
    * Make a list of TQL query.
    *
    * @param queries A list of queries
-       * @return A List of non-<code>null</code> answers to the <var>queries</var> .
+   * @return A List of non-<code>null</code> answers to the <var>queries</var>.
    *      The position of the answer corresponds to the position of the
-   *      parameter query.
+   *      parameter query. Each element of the list is either an Answer, or a RemoteAnswer,
+   *      which do not share a common parent class, hence the list of Objects.
    * @throws QueryException if <var>query</var> can't be answered
    * @throws RemoteException if the remote connection fails
    */
-  public List query(List queries) throws QueryException, RemoteException;
+  public List<Object> query(List<Query> queries) throws QueryException, RemoteException;
 
   /**
    * Extract {@link Rules} from the data found in a model.
@@ -283,9 +278,9 @@
    * Rules a set of {@link Rules} on its defined model.
    *
    * @param rules The rules to be run.
-   * @throws RulesException An error was encountered executing the rules.
+   * @throws QueryException An error was encountered executing the rules.
    */
-  public void applyRules(RulesRef rules) throws RulesException, RemoteException;
+  public void applyRules(RulesRef rules) throws QueryException, RemoteException;
 
   /**
    * Release resources associated with this session. The session won't be usable
@@ -308,4 +303,9 @@
   public void login(URI securityDomain, String username,
       char[] password) throws RemoteException;
 
+  /**
+   * Obtain an XAResource for this session.
+   */
+  public RemoteXAResource getXAResource() throws QueryException, RemoteException;
+  public RemoteXAResource getReadOnlyXAResource() throws QueryException, RemoteException;
 }

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionFactoryImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionFactoryImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionFactoryImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -244,8 +244,5 @@
   /**
    * {@inheritDoc RemoteSessionFactory}
    */
-  public void close() throws QueryException {
-
-    sessionFactory.close();
-  }
+  public void close() throws QueryException { }
 }

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionWrapperSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionWrapperSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteSessionWrapperSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *   XAResource access copyright 2007 The Topaz Foundation.
  *
  * [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
@@ -34,6 +35,7 @@
 import java.rmi.RemoteException;
 import java.util.*;
 import java.io.*;
+import javax.transaction.xa.XAResource;
 
 // Third party packages
 import org.apache.log4j.Logger;
@@ -44,7 +46,6 @@
 import org.mulgara.query.ModelExpression;
 import org.mulgara.query.Query;
 import org.mulgara.query.QueryException;
-import org.mulgara.rules.RulesException;
 import org.mulgara.rules.RulesRef;
 import org.mulgara.server.NonRemoteSessionException;
 import org.mulgara.server.Session;
@@ -210,7 +211,7 @@
   /**
    * {@inheritDoc}
    */
-  public void insert(URI modelURI, Set<Triple> statements) throws QueryException {
+  public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException {
 
     try {
       remoteSession.insert(modelURI, statements);
@@ -240,7 +241,7 @@
   /**
    * {@inheritDoc}
    */
-  public void delete(URI modelURI, Set<Triple> statements) throws QueryException {
+  public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException {
 
     try {
       remoteSession.delete(modelURI, statements);
@@ -435,15 +436,16 @@
 
     try {
 
-      List<Object> remoteAnswers = (List<Object>)remoteSession.query(queries);
+      List<Object> remoteAnswers = remoteSession.query(queries);
       resetRetries();
       List<Answer> localAnswers = new ArrayList<Answer>(remoteAnswers.size());
 
       for (Object ans: remoteAnswers) {
-        if (!(ans instanceof RemoteAnswer)) {
+        if (!(ans instanceof RemoteAnswer) && !(ans instanceof Answer)) {
           throw new QueryException("Non-answer returned from query.");
         }
-        localAnswers.add(new RemoteAnswerWrapperAnswer((RemoteAnswer)ans));
+        if (ans instanceof RemoteAnswer) localAnswers.add(new RemoteAnswerWrapperAnswer((RemoteAnswer)ans));
+        else localAnswers.add((Answer)ans);
       }
 
       return localAnswers;
@@ -602,12 +604,27 @@
   /**
    * {@inheritDoc}
    */
-  public void applyRules(RulesRef rules) throws RulesException {
+  public void applyRules(RulesRef rules) throws QueryException {
     try {
       remoteSession.applyRules(rules);
     } catch (RemoteException re) {
-      throw new RulesException("Java RMI reconnection failure", re);
+      throw new QueryException("Java RMI reconnection failure", re);
     }
   }
 
+  public XAResource getXAResource() throws QueryException {
+    try {
+      return new RemoteXAResourceWrapperXAResource(remoteSession.getXAResource());
+    } catch (RemoteException re){
+      throw new QueryException("Java RMI failure", re);
+    }
+  }
+
+  public XAResource getReadOnlyXAResource() throws QueryException {
+    try {
+      return new RemoteXAResourceWrapperXAResource(remoteSession.getReadOnlyXAResource());
+    } catch (RemoteException re){
+      throw new QueryException("Java RMI failure", re);
+    }
+  }
 }

Copied: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResource.java (from rev 722, trunk/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResource.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResource.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2007 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.server.rmi;
+
+// Java 2 standard packages
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.Category;
+
+// Local packages
+
+/**
+ * Remote XAResource.
+ *
+ */
+/**
+ * An analogue to XAResource that is suitable for implementing as an RMI object.
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ * @created 2007-11-28
+ * @licence Apache License v2.0
+ */
+public interface RemoteXAResource extends Remote
+{
+  public void commit(Xid xid, boolean onePhase) throws XAException, RemoteException;
+
+  public void end(Xid xid, int flags) throws XAException, RemoteException;
+
+  public void forget(Xid xid) throws XAException, RemoteException;
+
+  public int getTransactionTimeout() throws XAException, RemoteException;
+
+  public int prepare(Xid xid) throws XAException, RemoteException;
+
+  public Xid[] recover(int flag) throws XAException, RemoteException;
+
+  public void rollback(Xid xid) throws XAException, RemoteException;
+
+  public boolean setTransactionTimeout(int seconds) throws XAException, RemoteException;
+
+  public void start(Xid xid, int flags) throws XAException, RemoteException;
+
+  // Note: This provides distributed isSameRM
+  public Serializable getRMId() throws RemoteException;
+}

Copied: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResourceWrapperXAResource.java (from rev 722, trunk/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResourceWrapperXAResource.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResourceWrapperXAResource.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RemoteXAResourceWrapperXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2007 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.server.rmi;
+
+// Java 2 standard packages
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Arrays;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.*;
+
+// Local packages
+import org.mulgara.server.ResourceManagerInstanceAdaptor;
+
+/**
+ * Wraps an RMI RemoteXAResource and presents it as a pure XAResource.
+ *
+ * @created 2007-11-28
+ * @author Andrae Muys
+ * @licence Apache License v2.0
+ */
+class RemoteXAResourceWrapperXAResource implements XAResource, ResourceManagerInstanceAdaptor {
+  /** logger */
+  private static Logger logger =
+      Logger.getLogger(RemoteXAResourceWrapperXAResource.class.getName());
+
+  /**
+   * The wrapped instance.
+   */
+  private RemoteXAResource remoteResource;
+
+  /**
+   * Wrap a {@link RemoteAnswer} to make it into an {@link Answer}.
+   *
+   * @param remoteAnswer  the instance to wrap
+   * @throws IllegalArgumentException  if <var>remoteAnswer</var> is
+   *   <code>null</code>
+   */
+  RemoteXAResourceWrapperXAResource(RemoteXAResource remoteResource) throws RemoteException {
+    if (remoteResource == null) {
+      throw new IllegalArgumentException("Null 'remoteResource' parameter");
+    }
+
+    this.remoteResource = remoteResource;
+  }
+
+  //
+  // Methods implementing XAResource
+  //
+
+  public void commit(Xid xid, boolean onePhase) throws XAException {
+    try {
+      remoteResource.commit(convertXid(xid), onePhase);
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public void end(Xid xid, int flags) throws XAException {
+    try {
+      remoteResource.end(convertXid(xid), flags);
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public void forget(Xid xid) throws XAException {
+    try {
+      remoteResource.forget(convertXid(xid));
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public int getTransactionTimeout() throws XAException {
+    try {
+      return remoteResource.getTransactionTimeout();
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public boolean isSameRM(XAResource xares) throws XAException {
+    try {
+      if (xares == this) {
+        return true;
+      } else if (xares instanceof ResourceManagerInstanceAdaptor) {
+        try {
+          return ((ResourceManagerInstanceAdaptor)xares).getRMId().equals(remoteResource.getRMId());
+        } catch (UnsupportedOperationException eu) {
+          logger.debug("getRMId() unsupported on XAResource", eu);
+          return false;
+        }
+      } else {
+        return false;
+      }
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public Serializable getRMId() {
+    try {
+      return remoteResource.getRMId();
+    } catch (RemoteException er) {
+      throw new UnsupportedOperationException("Failed to obtain RMid", er);
+    }
+  }
+
+  public int prepare(Xid xid) throws XAException {
+    try {
+      return remoteResource.prepare(convertXid(xid));
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public Xid[] recover(int flag) throws XAException {
+    try {
+      return remoteResource.recover(flag);
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public void rollback(Xid xid) throws XAException {
+    try {
+      remoteResource.rollback(convertXid(xid));
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public boolean setTransactionTimeout(int seconds) throws XAException {
+    try {
+      return remoteResource.setTransactionTimeout(seconds);
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  public void start(Xid xid, int flags) throws XAException {
+    try {
+      remoteResource.start(convertXid(xid), flags);
+    } catch (RemoteException re) {
+      logger.warn("RMI Error in XAResource", re);
+      throw new XAException(XAException.XAER_RMFAIL);
+    }
+  }
+
+  private SerializableXid convertXid(Xid xid) {
+    return new SerializableXid(xid);
+  }
+
+  private static class SerializableXid implements Xid, Serializable {
+    private byte[] bq;
+    private int fi;
+    private byte[] gtid;
+
+    public SerializableXid(Xid xid) {
+      byte[] tbq = xid.getBranchQualifier();
+      byte[] tgtid = xid.getGlobalTransactionId();
+      this.bq = new byte[tbq.length];
+      this.fi = xid.getFormatId();
+      this.gtid = new byte[tgtid.length];
+      System.arraycopy(tbq, 0, this.bq, 0, tbq.length);
+      System.arraycopy(tgtid, 0, this.gtid, 0, tgtid.length);
+    }
+
+    public byte[] getBranchQualifier() {
+      return bq;
+    }
+
+    public int getFormatId() {
+      return fi;
+    }
+
+    public byte[] getGlobalTransactionId() {
+      return gtid;
+    }
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiServer.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiServer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiServer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,8 +29,6 @@
 
 
 // Java 2 standard packages
-import java.io.*;
-import java.lang.reflect.Constructor;
 import java.net.*;
 import java.rmi.*;
 import java.rmi.server.UnicastRemoteObject;
@@ -46,54 +44,47 @@
  * Java RMI server.
  *
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
  * @created 2002-01-12
- *
- * @version $Revision: 1.9 $
- *
- * @modified $Date: 2005/01/05 04:59:02 $
- *
- * @maintenanceAuthor $Author: newmana $
- *
- * @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
- * @copyright &copy; 2002-2003 <A href="http://www.PIsoftware.com/">Plugged In
- *      Software Pty Ltd</A>
- *
+ * @copyright &copy; 2002-2003 <A href="http://www.PIsoftware.com/">Plugged In Software Pty Ltd</A>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
- *
  * @see <a href="http://developer.java.sun.com/developer/JDCTechTips/2001/tt0327.html#jndi"/>
  *      <cite>JNDI lookup in distributed systems</cite> </a>
  */
 public class RmiServer extends AbstractServer implements RmiServerMBean {
 
-  /**
-   * Logger. This is named after the classname.
-   */
-  private final static Logger logger =
-    Logger.getLogger(RmiServer.class.getName());
+  /** Logger. This is named after the classname. */
+  private final static Logger logger = Logger.getLogger(RmiServer.class.getName());
 
-  /**
-   * The Java RMI registry naming context.
-   */
+  /** The name of the URL protocol handler package property. */
+  private static final String PROTOCOL_HANDLER = "java.protocol.handler.pkgs";
+
+  // Initialize the system to know about RMI URLs
+  static {
+    String handler = System.getProperty(PROTOCOL_HANDLER);
+    String thisPackage = RmiServer.class.getPackage().getName();
+    assert thisPackage.endsWith(".rmi");
+    String parentPackage = thisPackage.substring(0, thisPackage.lastIndexOf('.'));
+    System.setProperty(PROTOCOL_HANDLER, (handler == null) ? parentPackage : handler + "|" + parentPackage);
+  }
+
+  /** The default port used for RMI. */
+  public static final int DEFAULT_PORT = 1099;
+
+  /** The Java RMI registry naming context. */
   private Context rmiRegistryContext;
 
-  /**
-   * The RMI registry name of this server.
-   */
+  /** The RMI registry name of this server. */
   private String name;
 
   /**
    * The local copy of the RMI session factory. This reference must be held
    * because the garbage collector isn't aware of remote stubs on distant JVMs.
-   *
    */
   private RemoteSessionFactory remoteSessionFactory;
 
   /**
    * An RMI stub that proxies for {@link #remoteSessionFactory}. This instance
    * can be serialized and distributed to remote JVMs.
-   *
    */
   private RemoteSessionFactory exportedRemoteSessionFactory;
 
@@ -102,18 +93,13 @@
    * set <var>name</var> to <code>null</code>, but the
    * {@link org.mulgara.server.ServerMBean#start} action can't be used in that
    * case. The <var>name</var> cannot be set while the server is started.
-   *
    * @param name the new value
-   * @throws IllegalStateException if the server is started or if the database
-   *      already has a fixed URI
+   * @throws IllegalStateException if the server is started or if the database already has a fixed URI
    */
   public void setName(String name) {
-
     // Prevent the name from being changed while the server is up
     if (this.getState() == STARTED) {
-
-      throw new IllegalStateException(
-          "Can't change name without first stopping the server");
+      throw new IllegalStateException("Can't change name without first stopping the server");
     }
 
     // Set field
@@ -124,45 +110,44 @@
   /**
    * Sets the hostname of the server.
    *
-   * @param hostname the hostname of the server, if <code>null</code> <code>localhost</code>
-   *      will be used
-   * @throws IllegalStateException if the service is started or if the
-   *      underlying session factory already has a fixed hostname
+   * @param hostname the hostname of the server, if <code>null</code> <code>localhost</code> will be used
+   * @throws IllegalStateException if the service is started or if the underlying session factory already has a fixed hostname
    */
   public void setHostname(String hostname) {
-
     // Prevent the hostname from being changed while the server is up
     if (this.getState() == STARTED) {
-
-      throw new IllegalStateException(
-          "Can't change hostname without first stopping the server");
+      throw new IllegalStateException("Can't change hostname without first stopping the server");
     }
 
     // Reset the field
     if (hostname == null) {
-
       this.hostname = "localhost";
       logger.warn("Hostname supplied is null, defaulting to localhost");
-    }
-    else {
-
+    } else {
       this.hostname = hostname;
     }
 
     updateURI();
   }
 
+  /**
+   * Sets the server port.
+   * @param newPortNumber The new port to bind to.
+   */
+  public void setPortNumber(int newPortNumber) {
+    super.setPortNumber(newPortNumber);
+    updateURI();
+  }
+
   //
   // MBean properties
   //
 
   /**
    * Read the name the server is bound to in the RMI registry.
-   *
    * @return The bound name of the server.
    */
   public String getName() {
-
     return name;
   }
 
@@ -172,7 +157,6 @@
 
   /**
    * Start the server.
-   *
    * @throws IllegalStateException if <var>name</var> is <code>null</code>
    * @throws NamingException Error accessing RMI registry.
    * @throws RemoteException Error accessing RMI services.
@@ -180,19 +164,14 @@
   protected void startService() throws NamingException, RemoteException {
 
     // Validate "name" property
-    if (name == null) {
+    if (name == null) throw new IllegalStateException("Must set \"name\" property");
 
-      throw new IllegalStateException("Must set \"name\" property");
-    }
-
     // Initialize fields
     rmiRegistryContext = new InitialContext();
 
     // Apply RMI wrapper to the session factory
     remoteSessionFactory = new RemoteSessionFactoryImpl(getSessionFactory());
-    exportedRemoteSessionFactory =
-        (RemoteSessionFactory) UnicastRemoteObject.exportObject(
-        remoteSessionFactory);
+    exportedRemoteSessionFactory = (RemoteSessionFactory)UnicastRemoteObject.exportObject(remoteSessionFactory);
 
     // Bind the service to the RMI registry
     rmiRegistryContext.rebind(name, exportedRemoteSessionFactory);
@@ -200,55 +179,47 @@
 
   /**
    * Stop the server.
-   *
-   * @throws NamingException EXCEPTION TO DO
-   * @throws NoSuchObjectException EXCEPTION TO DO
+   * @throws NamingException Error accessing the registry.
+   * @throws NoSuchObjectException The current server is not registered in the registry.
    */
   protected void stopService() throws NamingException, NoSuchObjectException {
-
     rmiRegistryContext.unbind(name);
     UnicastRemoteObject.unexportObject(remoteSessionFactory, true);
   }
 
+  /**
+   * Creates a new URI for the current hostname/servicename/port and sets this service
+   * to register with that name.
+   * @throws Error if the hostname or service name cannot be encoded in a URI.
+   */
   private void updateURI() {
-
     URI newURI = null;
 
-    // A not null name means to override the default.  A null name will derive
-    // it from the RMIRegistry.
-    if (name != null) {
-
-      if (this.getHostname() == null) {
-
-        // try to use the local host name
-        try {
-
-          hostname = InetAddress.getLocalHost().getCanonicalHostName();
-        }
-        catch (Exception e) {
-
-          logger.warn("Problem getting host name! - using localhost");
-          hostname = "localhost";
-        }
+    if (hostname == null) {
+      // try to use the local host name
+      try {
+        hostname = InetAddress.getLocalHost().getCanonicalHostName();
+      } catch (Exception e) {
+        logger.warn("Problem getting host name! - using \"localhost\"");
+        hostname = "localhost";
       }
-      else {
-
-        hostname = this.getHostname();
-      }
     }
 
     // Generate new server URI
     try {
-
-      newURI = new URI("rmi", null, hostname, getPortNumber(), "/" + name, null,
-          null);
-    }
-    catch (URISyntaxException e) {
-
+      String path = "/" + (name == null ? "" : name);
+      int portValue = getPortNumber() == DEFAULT_PORT ? -1 : getPortNumber();
+      newURI = new URI("rmi", null, hostname, portValue, path, null, null);
+    } catch (URISyntaxException e) {
       throw new Error("Bad generated URI", e);
     }
 
     // Set URI.
     setURI(newURI);
   }
+  
+  /** @see org.mulgara.server.AbstractServer#getDefaultPort() */
+  protected int getDefaultPort() {
+    return DEFAULT_PORT;
+  }
 }

Copied: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiURLConnection.java (from rev 722, trunk/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiURLConnection.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiURLConnection.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/RmiURLConnection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,261 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.server.rmi;
+
+import java.util.Hashtable;
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.rmi.UnmarshalException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+import org.mulgara.util.ClassDescriber;
+import org.mulgara.util.ClassDescriberXML;
+
+/**
+ * This class represents a connection to an RMI server. Reading from this connection
+ * results in an Object coming across the connection, or an XML string to describe
+ * what could have come over if the RMI deserializer cannot find a local class to
+ * instantiate the object.
+ *
+ * @created Mar 28, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class RmiURLConnection extends URLConnection {
+
+  /** The context of the registry containing the RMI references. */
+  private Context rmiRegistryContext = null;
+
+  /** A string description of the object referenced by the URL. */
+  private String description = null;
+
+  /** An object representing what the URL refers to. If possible, this is a remote object, else a String. */
+  private Object content = null;
+
+  /** Contains the raw bytes representing the data that will be "read" from this connection. */
+  private byte[] buffer = null;
+
+  /**
+   * Build a URLConnection to an RMI server.
+   * @param url The URL to use for locating the service on the server.
+   */
+  protected RmiURLConnection(URL url) {
+    super(url);
+    setDefaultUseCaches(false);
+    setDefaultAllowUserInteraction(false);
+  }
+
+  /**
+   * This type of connection does not permit user interaction.
+   * @see java.net.URLConnection#setAllowUserInteraction(boolean)
+   */
+  public void setAllowUserInteraction(boolean allow) {
+    if (allow) throw new IllegalStateException("Not valid to interact with an rmi connection");
+  }
+
+  /**
+   * Caching is not valid for this kind of connection.
+   * @see java.net.URLConnection#setUseCaches(boolean)
+   */
+  public void setUseCaches(boolean use) {
+    if (use) throw new IllegalStateException("Not valid to cache an rmi connection");
+  }
+
+  /**
+   * Connects to the specified service, and gets what content it can.
+   * @see java.net.URLConnection#connect()
+   */
+  public void connect() throws IOException {
+    Hashtable<String,String> environment = new Hashtable<String,String>();
+    environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
+    environment.put(Context.PROVIDER_URL, url.getProtocol() + "://" + url.getAuthority());
+    String name = url.getPath().substring(1);
+    try {
+      rmiRegistryContext = new InitialContext(environment);
+      updateContent(name);
+    } catch (NamingException ne) {
+      ne.printStackTrace();
+      throw new IOException("Unable to establish connection: " + ne);
+    }
+  }
+
+  /**
+   * Reads the number of bytes for the content that can be read from this connection.
+   * @return The number of bytes that can be returned from {@link #getContent()}.
+   * @see java.net.URLConnection#getContentLength()
+   */
+  public int getContentLength() {
+    return (buffer == null) ? 0 : buffer.length;
+  }
+
+  /**
+   * Gets the data representing the service connected to.
+   * @return Either a remote object, accessed through RMI, or a String containing XML if
+   *   that object cannot be instantiated.
+   * @throws IOException If not connected.
+   * @see java.net.URLConnection#getContent()
+   */
+  public Object getContent() throws IOException {
+    if (content == null) throw new IOException("Not connected");
+    return content;
+  }
+
+  /**
+   * Gets the data representing the service connected to. Using a list of desired classes
+   * to specify the desired return type. The class array will be searched for a match with
+   * the following, with the first match being the returned type:
+   * <ol><li>The class of the Remote object obtained through RMI.</li>
+   * <li>{@link java.lang.String}: the result will contain an XML description of the object.</li>
+   * <li>An array of <code>byte</code>: the result will contain a serialization of either
+   *     the remote object or the XML description if the remote object cannot be instantiated.</li></ol>
+   * Otherwise, a <code>null</code> is returned.
+   * @return Either a remote object, accessed through RMI, or a String containing XML if
+   *   that object cannot be instantiated.
+   * @throws IOException If not connected.
+   * @see java.net.URLConnection#getContent()
+   */
+  @SuppressWarnings("unchecked")
+  public Object getContent(Class[] cls) throws IOException {
+    if (content == null) throw new IOException("Not connected");
+    if (testType(content.getClass(), cls)) return content;
+    if (testType(String.class, cls)) return description;
+    if (testType(byte[].class, cls)) return buffer;
+    return null;
+  }
+
+  /**
+   * Gets an input stream to read bytes from this connection.
+   * @return an input stream that will return the data of the content.
+   * @throws IOException If not connected.
+   * @see java.net.URLConnection#getInputStream()
+   */
+  public InputStream getInputStream() throws IOException {
+    if (buffer == null) throw new IOException("Not connected");
+    return new ByteArrayInputStream(buffer);
+  }
+
+  /**
+   * Utility to check if a class or one of its supertypes is present in an array.
+   * @param clazz The class to check for.
+   * @param cls The array of classes to test for the presence of clazz or one of its supertypes.
+   * @return <code>true</code> if the class or one of its supertypes is present in cls.
+   */
+  private static boolean testType(Class<?> clazz, Class<?>[] cls) {
+    for (Class<?> c: cls) if (c.isAssignableFrom(clazz)) return true;
+    return false;
+  }
+
+  /**
+   * Gets data from a server by name, and creates content at this side to represent it.
+   * Binary content will be created if possible, but a string containing an XML representation
+   * will always be created.
+   * @param name The name of the RMI service to get from the server.
+   * @throws NamingException Looking up the name on the server failed.
+   * @throws IOException Transfering data from the server failed.
+   */
+  private void updateContent(String name) throws NamingException, IOException {
+    if (name.length() == 0) {
+      // server only
+      description = getContextDescription(false);
+      content = description;
+      buffer = description.getBytes();
+    } else {
+      // service name. Get the object.
+      try {
+        Object content = rmiRegistryContext.lookup(name);
+        description = getServiceDescription(content);
+        buffer = (content instanceof Serializable) ? serialize((Serializable)content) : description.getBytes();
+      } catch (NamingException ne) {
+        Throwable e = ne.getCause();
+        if (!(e instanceof UnmarshalException)) throw ne;
+        if (e == null || !(e.getCause() instanceof ClassNotFoundException)) throw ne;
+        description = getContextDescription(true);
+        content = description;
+        buffer = description.getBytes();
+      }
+    }
+  }
+
+  /**
+   * Create an XML description of a {@link javax.naming.Context} from the server.
+   * @param outOfScope <code>true</code> if the class for this context is not in the classpath. 
+   * @return An XML string describing the current RMI context.
+   * @throws NamingException If the RMI context could not be accessed.
+   */
+  private String getContextDescription(boolean outOfScope) throws NamingException {
+    StringBuilder dsc = getHeader();
+    dsc.append("<context name=\"").append(rmiRegistryContext.getNameInNamespace()).append("\">\n");
+    NamingEnumeration<NameClassPair> ne = rmiRegistryContext.list("");
+    while (ne.hasMore()) {
+      NameClassPair nc = ne.next();
+      dsc.append("  <name value=\"").append(nc.getName());
+      if (nc.isRelative()) dsc.append("\" relative=\"").append(nc.isRelative());
+      dsc.append("\">\n");
+
+      dsc.append("    <class name=\"").append(nc.getClassName()).append("\"");
+      if (outOfScope) dsc.append(" inscope=\"false\"");
+      dsc.append("/>\n  </name>\n");
+    }
+    dsc.append("</context>");
+    return dsc.toString();
+  }
+
+  /**
+   * Create an XML description of an RMI service.
+   * @param obj The Remote RMI object representing the service.
+   * @return An XML string describing the service class.
+   * @throws NamingException If the RMI data could not be read.
+   */
+  private String getServiceDescription(Object obj) throws NamingException {
+    ClassDescriber cd = new ClassDescriberXML(obj);
+    StringBuilder b = getHeader().append("<service>\n");
+    b.append(cd.getDescription(1));
+    b.append("</service>");
+    return b.toString();
+  }
+
+  /**
+   * Creates a {@link java.lang.StringBuilder} containing an XML header. This is ready to have
+   * more data appended to it.
+   * @return A new StringBuilder with the header in it.
+   */
+  private static StringBuilder getHeader() {
+    StringBuilder header = new StringBuilder("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n\n");
+    return header;
+  }
+
+  /**
+   * Convert an object into an array of bytes.
+   * @param obj The object to serialize.
+   * @return a <code>byte[]</code> containing the serialization of obj.
+   * @throws IOException If there was an internal serialization error.
+   */
+  private byte[] serialize(Serializable obj) throws IOException {
+    ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
+    ObjectOutputStream out = new ObjectOutputStream(dataOut);
+    out.writeObject(obj);
+    return dataOut.toByteArray();
+  }
+
+}

Modified: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/SessionWrapperRemoteSession.java
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/SessionWrapperRemoteSession.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/SessionWrapperRemoteSession.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -16,7 +16,8 @@
  * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
  * Plugged In Software Pty Ltd. All Rights Reserved.
  *
- * Contributor(s): N/A.
+ * Contributor(s):
+ *   XAResource access copyright 2007 The Topaz Foundation.
  *
  * [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
@@ -31,14 +32,13 @@
 import java.io.*;
 import java.net.URI;
 import java.rmi.*;
-import java.rmi.server.UnicastRemoteObject;
 import java.util.*;
 
 // Third party packages
-import org.jrdf.graph.*;
 import org.apache.log4j.Logger;
 
 // Locally written packages
+import org.jrdf.graph.Triple;
 import org.mulgara.query.Answer;
 import org.mulgara.query.ArrayAnswer;
 import org.mulgara.query.ModelExpression;
@@ -57,28 +57,19 @@
  * {@link RemoteSession}.
  *
  * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
  * @created 2002-01-03
- *
- * @version $Revision: 1.11 $
- *
- * @modified $Date: 2005/06/26 12:48:16 $ by $Author: pgearon $
- *
  * @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
  * @copyright &copy; 2002-2003 <A href="http://www.PIsoftware.com/">Plugged In
  *      Software Pty Ltd</A>
- *
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 class SessionWrapperRemoteSession implements RemoteSession {
 
+  @SuppressWarnings("unused")
   /** Logger.  */
   private static final Logger logger = Logger.getLogger(SessionWrapperRemoteSession.class.getName());
 
-  /**
-   * The wrapped {@link Session}
-   */
+  /** The wrapped {@link Session} */
   private final Session session;
 
   //
@@ -92,11 +83,8 @@
   protected SessionWrapperRemoteSession(Session session) {
 
     // Validate "session" parameter
-    if (session == null) {
+    if (session == null) throw new IllegalArgumentException("Null \"session\" parameter");
 
-      throw new IllegalArgumentException("Null \"session\" parameter");
-    }
-
     // Initialize fields
     this.session = session;
   }
@@ -110,12 +98,10 @@
    * @throws QueryException EXCEPTION TO DO
    * @throws RemoteException EXCEPTION TO DO
    */
-  public long setModel(URI uri,
-      ModelExpression modelExpression) throws QueryException, RemoteException {
+  public long setModel(URI uri, ModelExpression modelExpression) throws QueryException, RemoteException {
     try {
       return session.setModel(uri, modelExpression);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -129,14 +115,10 @@
    * @return The number of statements inserted into the model
    * @throws QueryException if the model can't be modified
    */
-  public long setModel(InputStream inputStream, URI uri,
-                       ModelExpression modelExpression)
-    throws QueryException {
-
+  public long setModel(InputStream inputStream, URI uri, ModelExpression modelExpression) throws QueryException {
     try {
       return session.setModel(inputStream, uri, modelExpression);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -149,13 +131,10 @@
    * @throws QueryException EXCEPTION TO DO
    * @throws RemoteException EXCEPTION TO DO
    */
-  public void setAutoCommit(boolean autoCommit) throws QueryException,
-      RemoteException {
-
+  public void setAutoCommit(boolean autoCommit) throws QueryException, RemoteException {
     try {
       session.setAutoCommit(autoCommit);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -164,46 +143,34 @@
   // Methods implementing the RemoteSession interface
   //
 
-  public void insert(URI modelURI, Set statements) throws QueryException,
-      RemoteException {
-
+  public void insert(URI modelURI, Set<? extends Triple> statements) throws QueryException, RemoteException {
     try {
       session.insert(modelURI, statements);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
-  public void insert(URI modelURI, Query query) throws QueryException,
-      RemoteException {
-
+  public void insert(URI modelURI, Query query) throws QueryException, RemoteException {
     try {
       session.insert(modelURI, query);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
-  public void delete(URI modelURI, Set statements) throws QueryException,
-      RemoteException {
-
+  public void delete(URI modelURI, Set<? extends Triple> statements) throws QueryException, RemoteException {
     try {
       session.delete(modelURI, statements);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
-  public void delete(URI modelURI, Query query) throws QueryException,
-      RemoteException {
-
+  public void delete(URI modelURI, Query query) throws QueryException, RemoteException {
     try {
       session.delete(modelURI, query);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -216,13 +183,10 @@
    * @param destinationURI The URI of the file to backup into.
    * @throws QueryException if the backup cannot be completed.
    */
-  public void backup(URI sourceURI, URI destinationURI) throws QueryException,
-      RemoteException {
-
+  public void backup(URI sourceURI, URI destinationURI) throws QueryException, RemoteException {
     try {
       session.backup(sourceURI, destinationURI);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -235,13 +199,10 @@
    * @param outputStream The stream to receive the contents
    * @throws QueryException if the backup cannot be completed.
    */
-  public void backup(URI sourceURI, OutputStream outputStream)
-    throws QueryException, RemoteException {
-
+  public void backup(URI sourceURI, OutputStream outputStream) throws QueryException, RemoteException {
     try {
       session.backup(sourceURI, outputStream);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -255,13 +216,10 @@
    * @param sourceURI The URI of the backup file to restore from.
    * @throws QueryException if the restore cannot be completed.
    */
-  public void restore(URI serverURI, URI sourceURI) throws QueryException,
-      RemoteException {
-
+  public void restore(URI serverURI, URI sourceURI) throws QueryException, RemoteException {
     try {
       session.restore(serverURI, sourceURI);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -277,92 +235,85 @@
    * @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 serverURI, URI sourceURI)
-      throws QueryException, RemoteException {
-
+  public void restore(InputStream inputStream, URI serverURI, URI sourceURI) throws QueryException, RemoteException {
     try {
       session.restore(inputStream, serverURI, sourceURI);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
-
   }
 
 
   /**
-   * METHOD TO DO
+   * Adds a new graph to the SystemGraph set.
    *
-   * @param modelURI PARAMETER TO DO
-   * @param modelTypeURI PARAMETER TO DO
-   * @throws QueryException EXCEPTION TO DO
-   * @throws RemoteException EXCEPTION TO DO
+   * @param graphURI The URI of the graph to create.
+   * @param graphTypeURI The URI of the type for the new graph.
+   * @throws QueryException Unable to create the new graph.
+   * @throws RemoteException Network error attempting to create the new graph.
    */
-  public void createModel(URI modelURI, URI modelTypeURI) throws QueryException,
-      RemoteException {
-
+  public void createModel(URI modelURI, URI modelTypeURI) throws QueryException, RemoteException {
     try {
       session.createModel(modelURI, modelTypeURI);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
   /**
-   * METHOD TO DO
+   * Remove a graph and all its statements.
    *
-   * @param uri PARAMETER TO DO
-   * @throws QueryException EXCEPTION TO DO
-   * @throws RemoteException EXCEPTION TO DO
+   * @param uri The URI of the graph.
+   * @throws QueryException Unable to remove the graph.
+   * @throws RemoteException Network error attempting to remove the new graph.
    */
   public void removeModel(URI uri) throws QueryException, RemoteException {
-
     try {
       session.removeModel(uri);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
+  /**
+   * Tests if a graph exists.
+   * @param uri the URI of the graph.
+   * @see org.mulgara.server.rmi.RemoteSession#modelExists(java.net.URI)
+   */
   public boolean modelExists(URI uri) throws QueryException, RemoteException {
     try {
       return session.modelExists(uri);
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
   /**
-   * METHOD TO DO
+   * Commits a transaction on this session.
+   * NOTE: This is not for general use. Use the transaction API.
    *
-   * @throws QueryException EXCEPTION TO DO
-   * @throws RemoteException EXCEPTION TO DO
+   * @throws QueryException Unable to commit the transaction.
+   * @throws RemoteException There was a network error.
    */
   public void commit() throws QueryException, RemoteException {
-
     try {
       session.commit();
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
 
   /**
-   * METHOD TO DO
+   * Rolls back a transaction on this session.
+   * NOTE: This is not for general use. Use the transaction API.
    *
-   * @throws QueryException EXCEPTION TO DO
-   * @throws RemoteException EXCEPTION TO DO
+   * @throws QueryException Unable to roll back the transaction.
+   * @throws RemoteException There was a network error.
    */
   public void rollback() throws QueryException, RemoteException {
-
     try {
       session.rollback();
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -385,16 +336,13 @@
               ArrayAnswer(ans));
           ans.close();
           return serialAnswer;
-        }
-        else {
+        } else {
           return new AnswerWrapperRemoteAnswer(ans);
         }
-      }
-      catch (TuplesException e) {
+      } catch (TuplesException e) {
         throw new QueryException("Error getting information for answer", e);
       }
-    }
-    catch (Throwable t) {
+    } catch (Throwable t) {
       throw convertToQueryException(t);
     }
   }
@@ -408,31 +356,27 @@
    * @throws QueryException There was an exception on one of the queries, or a query returned a non-Answer.
    * @throws RemoteException Thrown when there is a network error.
    */
-  public List query(List queries) throws QueryException, RemoteException {
+  public List<Object> query(List<Query> queries) throws QueryException, RemoteException {
 
     try {
-      List localAnswers = session.query(queries);
-      List servedAnswers = new ArrayList(localAnswers.size());
+      List<Answer> localAnswers = session.query(queries);
+      List<Object> servedAnswers = new ArrayList<Object>(localAnswers.size());
 
-      Iterator i = localAnswers.iterator();
+      Iterator<Answer> i = localAnswers.iterator();
       while (i.hasNext()) {
         Object servedAnswer = null;
-        Object ans = i.next();
-        if (!(ans instanceof Answer))
-          throw new QueryException("Non-answer returned from query.");
+        Answer ans = i.next();
         try {
-          if (((Answer) ans).getRowUpperBound() <= RemoteAnswer.MARSHALL_SIZE_LIMIT) {
+          if (ans.getRowUpperBound() <= RemoteAnswer.MARSHALL_SIZE_LIMIT) {
             // don't need to wrap this in an
             // AnswerWrapperRemoteAnswerSerialised as the other end can handle
             // any kind of object as it comes out of the list
-            servedAnswer = new ArrayAnswer((Answer) ans);
+            servedAnswer = new ArrayAnswer(ans);
+          } else {
+            servedAnswer = new AnswerWrapperRemoteAnswer(ans);
           }
-          else {
-            servedAnswer = new AnswerWrapperRemoteAnswer((Answer) ans);
-          }
-          ((Answer) ans).close();
-        }
-        catch (TuplesException e) {
+          ans.close();
+        } catch (TuplesException e) {
           throw new QueryException("Error getting information for answer", e);
         }
         servedAnswers.add(servedAnswer);
@@ -475,13 +419,13 @@
    * @param rules The rules to be run.
    * @throws RulesException An error was encountered executing the rules.
    */ 
-  public void applyRules(RulesRef rules) throws RulesException, RemoteException {
+  public void applyRules(RulesRef rules) throws QueryException, RemoteException {
     try {
       session.applyRules(rules);
-    } catch (RulesException re) {
+    } catch (QueryException re) {
       throw re;
     } catch (Throwable t) {
-      throw new RulesException(t.toString(), t);
+      throw new QueryException(t.toString(), t);
     }
   }
 
@@ -515,11 +459,29 @@
     session.login(securityDomain, username, password);
   }
 
+
+  public RemoteXAResource getXAResource() throws QueryException, RemoteException {
+    try {
+      return new XAResourceWrapperRemoteXAResource(session.getXAResource());
+    } catch (Throwable t) {
+      throw convertToQueryException(t);
+    }
+  }
+
+  public RemoteXAResource getReadOnlyXAResource() throws QueryException, RemoteException {
+    try {
+      return new XAResourceWrapperRemoteXAResource(session.getReadOnlyXAResource());
+    } catch (Throwable t) {
+      throw convertToQueryException(t);
+    }
+  }
+
+
   // Construct an exception chain that will pass over RMI.
   protected Throwable mapThrowable(Throwable t) {
     Throwable cause = t.getCause();
     Throwable mappedCause = cause != null ? mapThrowable(cause) : null;
-    Class tClass = t.getClass();
+    Class<? extends Throwable> tClass = t.getClass();
     String tClassName = tClass.getName();
 
     if (

Copied: branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/XAResourceWrapperRemoteXAResource.java (from rev 722, trunk/src/jar/server-rmi/java/org/mulgara/server/rmi/XAResourceWrapperRemoteXAResource.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/XAResourceWrapperRemoteXAResource.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/server-rmi/java/org/mulgara/server/rmi/XAResourceWrapperRemoteXAResource.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2007 The Topaz Foundation 
+ *
+ * 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.
+ *
+ * Contributions:
+ */
+package org.mulgara.server.rmi;
+
+// Java 2 standard packages
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.*;
+
+// Local packages
+import org.mulgara.server.ResourceManagerInstanceAdaptor;
+
+/**
+ * Wraps an XAResource and makes it available as an RMI object.
+ *
+ * @created 2007-11-28
+ * @author Andrae Muys
+ * @licence Apache License v2.0
+ */
+public class XAResourceWrapperRemoteXAResource
+    extends UnicastRemoteObject implements RemoteXAResource {
+  /** logger */
+  private static Logger logger =
+      Logger.getLogger(XAResourceWrapperRemoteXAResource.class.getName());
+
+  protected final XAResource resource;
+  protected final ResourceManagerInstanceAdaptor adaptor;
+
+  public XAResourceWrapperRemoteXAResource(XAResource resource) throws RemoteException {
+    if (resource == null) {
+      throw new IllegalArgumentException("Null 'resource' parameter");
+    }
+
+    this.resource = resource;
+    this.adaptor = resource instanceof ResourceManagerInstanceAdaptor ?
+      (ResourceManagerInstanceAdaptor)resource : null;
+  }
+
+  public void commit(Xid xid, boolean onePhase) throws XAException, RemoteException {
+    resource.commit(xid, onePhase);
+  }
+
+  public void end(Xid xid, int flags) throws XAException, RemoteException {
+    resource.end(xid, flags);
+  }
+
+  public void forget(Xid xid) throws XAException, RemoteException {
+    resource.forget(xid);
+  }
+
+  public int getTransactionTimeout() throws XAException, RemoteException {
+    return resource.getTransactionTimeout();
+  }
+
+  public boolean isSameRM(XAResource xares) throws XAException, RemoteException {
+    return resource.isSameRM(xares);
+  }
+
+  public int prepare(Xid xid) throws XAException, RemoteException {
+    return resource.prepare(xid);
+  }
+
+  public Xid[] recover(int flag) throws XAException, RemoteException {
+    return resource.recover(flag);
+  }
+
+  public void rollback(Xid xid) throws XAException, RemoteException {
+    resource.rollback(xid);
+  }
+
+  public boolean setTransactionTimeout(int seconds) throws XAException, RemoteException {
+    return resource.setTransactionTimeout(seconds);
+  }
+
+  public void start(Xid xid, int flags) throws XAException, RemoteException {
+    resource.start(xid, flags);
+  }
+
+  public Serializable getRMId() throws RemoteException, UnsupportedOperationException {
+    if (adaptor == null) {
+      throw new UnsupportedOperationException("Wrapped XAResource does not support remote-id");
+    } else {
+      return adaptor.getRMId();
+    }
+  }
+}

Modified: branches/mgr-61-sparql/src/jar/sparql-protocol/java/org/mulgara/sparql/protocol/StreamAnswerTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/sparql-protocol/java/org/mulgara/sparql/protocol/StreamAnswerTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/sparql-protocol/java/org/mulgara/sparql/protocol/StreamAnswerTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 // Third party packages
 import junit.framework.*;          // JUnit
 import junit.textui.TestRunner;
-import org.apache.log4j.Category;  // Log4J
+import org.apache.log4j.Logger;    // Log4J
 import org.jrdf.graph.Literal;     // JRDF
 import org.jrdf.graph.URIReference;
 
@@ -64,7 +64,7 @@
   /**
   * Logger.
   */
-  private Category logger = Category.getInstance(getClass().getName());
+  private static final Logger logger = Logger.getLogger(StreamAnswerTest.class);
 
   /**
   * Constructs a new answer test with the given name.

Modified: branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third-party packages
-import org.apache.log4j.Category;  // log4j classes
+import org.apache.log4j.Logger;  // log4j classes
 
 // Locally written packages
 import org.mulgara.store.nodepool.*;
@@ -62,8 +62,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(XANodePoolImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(XANodePoolImpl.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImplTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImplTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-nodepool-xa/java/org/mulgara/store/nodepool/xa/XANodePoolImplTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.*;
@@ -58,8 +58,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(XANodePoolImplTest.class.getName());
+  private final static Logger logger = Logger.getLogger(XANodePoolImplTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPObject.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPObject.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPObject.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,6 @@
 import java.nio.charset.Charset;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPStringComparator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPStringComparator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPStringComparator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,6 @@
 import java.nio.CharBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPTypedLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPTypedLiteral.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/AbstractSPTypedLiteral.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.LiteralImpl;
@@ -63,8 +63,7 @@
 public abstract class AbstractSPTypedLiteral extends AbstractSPObject
       implements SPTypedLiteral {
 
-  private static final Category logger =
-      Category.getInstance(AbstractSPTypedLiteral.class.getName());
+  private static final Logger logger = Logger.getLogger(AbstractSPTypedLiteral.class);
 
   protected int typeId;
   protected int subtypeId;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/StringPoolAbstractTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/StringPoolAbstractTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/StringPoolAbstractTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.nodepool.NodePool;
@@ -65,8 +65,7 @@
   /**
    * The category to log to.
    */
-  private static Category log =
-    Category.getInstance(StringPoolAbstractTest.class.getName());
+  private static final Logger log = Logger.getLogger(StringPoolAbstractTest.class);
 
   /**
    * Subclasses must initialize this field.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.*;
@@ -59,8 +59,7 @@
  */
 public final class SPBase64BinaryFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPBase64BinaryFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPBase64BinaryFactory.class);
 
 
   /**

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBase64BinaryImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -66,8 +66,7 @@
     implements SPTypedLiteral {
 
   /** Logger */
-  private static final Category logger =
-      Category.getInstance(SPBase64BinaryImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(SPBase64BinaryImpl.class);
 
   /** Type code that identifies this type */
   static final int TYPE_ID = 13;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBinaryComparator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBinaryComparator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBinaryComparator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,6 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.store.stringpool.SPComparator;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.*;
@@ -59,8 +59,7 @@
  */
 public final class SPBooleanFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPBooleanFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPBooleanFactory.class);
 
 
   /**

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPBooleanImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -64,8 +64,7 @@
     implements SPTypedLiteral {
 
   /** Logger */
-  private static final Category logger =
-      Category.getInstance(SPBooleanImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(SPBooleanImpl.class);
 
   /** Type code that identifies this type */
   static final int TYPE_ID = 12;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseInsensitiveStringComparator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseInsensitiveStringComparator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseInsensitiveStringComparator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,6 @@
 import java.nio.CharBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.store.stringpool.AbstractSPStringComparator;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseSensitiveStringComparator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseSensitiveStringComparator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPCaseSensitiveStringComparator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,6 @@
 import java.nio.CharBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.store.stringpool.AbstractSPStringComparator;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -58,8 +58,7 @@
  */
 public final class SPDateFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPDateFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDateFactory.class);
 
 
   public int getTypeId() {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Locale;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Date utils
 import com.mousepushers.date.DateParser;
@@ -69,8 +69,7 @@
  */
 public final class SPDateImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPDateImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDateImpl.class);
 
   static final int TYPE_ID = 5; // Unique ID
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -58,8 +58,7 @@
  */
 public final class SPDateTimeFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPDateTimeFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDateTimeFactory.class);
 
 
   public int getTypeId() {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDateTimeImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Locale;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Date utils
 import com.mousepushers.date.DateParser;
@@ -69,8 +69,7 @@
  */
 public final class SPDateTimeImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPDateTimeImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDateTimeImpl.class);
 
   static final int TYPE_ID = 6; // Unique ID
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
@@ -61,8 +61,7 @@
  */
 public final class SPDecimalFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPDecimalFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDecimalFactory.class);
 
   private final static URI[] TYPE_URIS = {
       URI.create(XSD.NAMESPACE + "decimal"),

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
@@ -63,8 +63,7 @@
  */
 public final class SPDecimalImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPDecimalImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDecimalImpl.class);
 
   private long l;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -60,8 +60,7 @@
  */
 public final class SPDoubleFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPDoubleFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDoubleFactory.class);
 
 
   public int getTypeId() {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDoubleImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
@@ -62,8 +62,7 @@
 public final class SPDoubleImpl extends AbstractSPTypedLiteral
       implements SPDouble {
 
-  private final static Category logger =
-      Category.getInstance(SPDoubleImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPDoubleImpl.class);
 
   private double d;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -60,8 +60,7 @@
  */
 public final class SPFloatFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPFloatFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPFloatFactory.class);
 
 
   public int getTypeId() {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPFloatImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
@@ -61,8 +61,7 @@
  */
 public final class SPFloatImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPFloatImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPFloatImpl.class);
 
   private float f;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -61,8 +61,7 @@
 public final class SPGDayFactory implements SPTypedLiteralFactory {
 
   /** Logging for the class */
-  private final static Category logger =
-                                     Category.getInstance(SPGDayFactory.class);
+  private final static Logger logger = Logger.getLogger(SPGDayFactory.class);
 
   /**
    * Retrieves the type id for this data type.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Calendar;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import com.hp.hpl.jena.datatypes.xsd.impl.XSDDayType;
 import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 import com.hp.hpl.jena.datatypes.DatatypeFormatException;
@@ -67,8 +67,7 @@
  */
 public final class SPGDayImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPGDayImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPGDayImpl.class);
 
   /** The date representation for the day */
   private Calendar day;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -61,8 +61,7 @@
 public final class SPGMonthDayFactory implements SPTypedLiteralFactory {
 
   /** Logging for the class */
-  private final static Category logger =
-                                     Category.getInstance(SPGMonthDayFactory.class);
+  private final static Logger logger = Logger.getLogger(SPGMonthDayFactory.class);
 
   /**
    * Retrieves the type id for this data type.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Calendar;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import com.hp.hpl.jena.datatypes.xsd.impl.XSDMonthDayType;
 import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 import com.hp.hpl.jena.datatypes.DatatypeFormatException;
@@ -68,8 +68,7 @@
  */
 public final class SPGMonthDayImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPGMonthDayImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPGMonthDayImpl.class);
 
   /** The date representation for the monthDay */
   private Calendar monthDay;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -61,8 +61,7 @@
 public final class SPGMonthFactory implements SPTypedLiteralFactory {
 
   /** Logging for the class */
-  private final static Category logger =
-                                     Category.getInstance(SPGMonthFactory.class);
+  private final static Logger logger = Logger.getLogger(SPGMonthFactory.class);
 
   /**
    * Retrieves the type id for this data type.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Calendar;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import com.hp.hpl.jena.datatypes.xsd.impl.XSDMonthType;
 import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 import com.hp.hpl.jena.datatypes.DatatypeFormatException;
@@ -67,8 +67,7 @@
  */
 public final class SPGMonthImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPGMonthImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPGMonthImpl.class);
 
   /** The date representation for the month */
   private Calendar month;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -61,8 +61,7 @@
 public final class SPGYearFactory implements SPTypedLiteralFactory {
 
   /** Logging for the class */
-  private final static Category logger =
-                                     Category.getInstance(SPGYearFactory.class);
+  private final static Logger logger = Logger.getLogger(SPGYearFactory.class);
 
   /**
    * Retrieves the type id for this data type.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Calendar;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import com.hp.hpl.jena.datatypes.xsd.impl.XSDYearType;
 import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 import com.hp.hpl.jena.datatypes.DatatypeFormatException;
@@ -67,8 +67,7 @@
  */
 public final class SPGYearImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPGYearImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPGYearImpl.class);
 
   /** The date representation for the year */
   private Calendar year;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -61,8 +61,7 @@
 public final class SPGYearMonthFactory implements SPTypedLiteralFactory {
 
   /** Logging for the class */
-  private final static Category logger =
-                                     Category.getInstance(SPGYearMonthFactory.class);
+  private final static Logger logger = Logger.getLogger(SPGYearMonthFactory.class);
 
   /**
    * Retrieves the type id for this data type.

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.Calendar;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import com.hp.hpl.jena.datatypes.xsd.impl.XSDYearMonthType;
 import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 import com.hp.hpl.jena.datatypes.DatatypeFormatException;
@@ -68,8 +68,7 @@
  */
 public final class SPGYearMonthImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPGYearMonthImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPGYearMonthImpl.class);
 
   /** The date representation for the yearMonth */
   private Calendar yearMonth;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.*;
@@ -59,8 +59,7 @@
  */
 public final class SPHexBinaryFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPHexBinaryFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPHexBinaryFactory.class);
 
 
   /**

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPHexBinaryImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -66,8 +66,7 @@
     implements SPTypedLiteral {
 
   /** Logger */
-  private static final Category logger =
-      Category.getInstance(SPHexBinaryImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(SPHexBinaryImpl.class);
 
   /** Type code that identifies this type */
   static final int TYPE_ID = 14;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPObjectFactoryImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPObjectFactoryImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPObjectFactoryImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,6 @@
 import org.jrdf.graph.URIReference;
 
 // Third party packages
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPStringImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPStringImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPStringImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.LiteralImpl;
@@ -60,8 +60,7 @@
  */
 public final class SPStringImpl extends AbstractSPObject implements SPString {
 
-  private final static Category logger =
-      Category.getInstance(SPStringImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPStringImpl.class);
 
   private String str;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPTypedLiteralRegistry.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPTypedLiteralRegistry.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPTypedLiteralRegistry.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.LiteralImpl;
@@ -62,8 +62,7 @@
  */
 public abstract class SPTypedLiteralRegistry {
 
-  private static final Category logger =
-      Category.getInstance(SPTypedLiteralRegistry.class.getName());
+  private static final Logger logger = Logger.getLogger(SPTypedLiteralRegistry.class);
 
   // TODO the class names of these factories should be in a configuration file.
   private static final SPTypedLiteralFactory[] DATATYPE_HANDLERS = {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPURIImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPURIImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPURIImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.net.URI;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.URIReferenceImpl;
@@ -64,8 +64,7 @@
   /**
    * Description of the Field
    */
-  private final static Category logger =
-      Category.getInstance(SPURIImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPURIImpl.class);
 
   private URI uri;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -57,8 +57,7 @@
  */
 public final class SPXMLLiteralFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPXMLLiteralFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPXMLLiteralFactory.class);
 
   public int getTypeId() {
     return SPXMLLiteralImpl.TYPE_ID;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXMLLiteralImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -71,8 +71,7 @@
   /**
    * Logger
    */
-  private static final Category logger =
-      Category.getInstance(SPXMLLiteralImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(SPXMLLiteralImpl.class);
 
   /**
    * Type code that identifies this type

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.store.stringpool.*;
@@ -60,8 +60,7 @@
  */
 public final class SPXSDStringFactory implements SPTypedLiteralFactory {
 
-  private final static Category logger =
-      Category.getInstance(SPXSDStringFactory.class.getName());
+  private final static Logger logger = Logger.getLogger(SPXSDStringFactory.class);
 
 
   public int getTypeId() {

Modified: branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPXSDStringImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.nio.ByteBuffer;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
@@ -63,8 +63,7 @@
  */
 public final class SPXSDStringImpl extends AbstractSPTypedLiteral {
 
-  private final static Category logger =
-      Category.getInstance(SPXSDStringImpl.class.getName());
+  private final static Logger logger = Logger.getLogger(SPXSDStringImpl.class);
 
   private String str;
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -135,7 +135,6 @@
       smallestSPObjects[s] = new SPLimit(s, true);
       largestSPObjects[s] = new SPLimit(s, false);
     }
-
   }
 
   //
@@ -203,7 +202,7 @@
       }
       else {
 
-        if (logger.isEnabledFor(Priority.ERROR)) {
+        if (logger.isEnabledFor(Level.ERROR)) {
 
           logger.error("The retrieved node and the given node were unequal " +
               "when removing node: " + gNode);
@@ -355,7 +354,10 @@
           "Finding typed literal nodes on the in memory string pool is not supported"
       );
     }
-    SortedSet subset = stringIndex.subSet(smallestSPObjects[typeCategory.ID], largestSPObjects[typeCategory.ID]);
+
+    SortedSet subset = typeCategory != null ?
+        stringIndex.subSet(smallestSPObjects[typeCategory.ID], largestSPObjects[typeCategory.ID]) : stringIndex;
+
     return new SetWrapperTuples(subset);
   }
 

Modified: branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImplTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImplTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool-memory/java/org/mulgara/store/stringpool/memory/MemoryStringPoolImplTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,6 @@
 
 // third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;

Modified: branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -79,8 +79,7 @@
 public final class XAStringPoolImpl implements XAStringPool {
 
   /** Logger. */
-  private static final Category logger =
-      Category.getInstance(XAStringPoolImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(XAStringPoolImpl.class);
 
   /** Single setting to enable the cache. */
   private static final boolean CACHE_ENABLED = true;
@@ -2238,15 +2237,14 @@
         }
 
         // Retrieve bytes from the AVLNode.
-        ByteBuffer data = ByteBuffer.allocate(dataSize);
-        data.limit(directDataSize);
-        avlNode.getBlock().get(
-            (AVLNode.HEADER_SIZE + IDX_DATA) * Constants.SIZEOF_LONG, data
-        );
+        ByteBuffer data = avlNode.getBlock().getSlice((AVLNode.HEADER_SIZE + IDX_DATA) * Constants.SIZEOF_LONG, directDataSize);
 
         // Retrieve the remaining bytes if any.
         if (dataSize > MAX_DIRECT_DATA_BYTES) {
-          data.limit(dataSize);
+          // need a bigger buffer
+          ByteBuffer newData = ByteBuffer.allocate(dataSize);
+          newData.put(data);
+          data = newData;
           retrieveRemainingBytes(objectPool, data, blockId);
         }
         data.rewind();

Modified: branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImplTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImplTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolImplTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 
 // third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 
 // locally written packages
@@ -76,8 +76,7 @@
  */
 public class XAStringPoolImplTest extends StringPoolAbstractTest {
 
-  private final static Category logger =
-      Category.getInstance(XAStringPoolImplTest.class.getName());
+  private final static Logger logger = Logger.getLogger(XAStringPoolImplTest.class);
 
 
   /**

Modified: branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolLoadTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolLoadTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-stringpool-xa/java/org/mulgara/store/stringpool/xa/XAStringPoolLoadTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // locally written packages
 import org.mulgara.store.stringpool.*;
@@ -66,8 +66,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(XAStringPoolLoadTest.class.getName());
+  private final static Logger logger = Logger.getLogger(XAStringPoolLoadTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/store-xa/java/org/mulgara/store/xa/SimpleXAResourceException.java
===================================================================
--- branches/mgr-61-sparql/src/jar/store-xa/java/org/mulgara/store/xa/SimpleXAResourceException.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/store-xa/java/org/mulgara/store/xa/SimpleXAResourceException.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
 
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * @created 2001-09-20
@@ -54,8 +54,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-    Category.getInstance(SimpleXAResourceException.class.getName());
+  private final static Logger logger = Logger.getLogger(SimpleXAResourceException.class);
 
   public SimpleXAResourceException(String message) {
     super(message);

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/ConstrainedNegationTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/ConstrainedNegationTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/ConstrainedNegationTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,7 +30,7 @@
 package org.mulgara.store.tuples;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Standard Java packages
 import java.util.*;
@@ -66,8 +66,7 @@
  */
 class ConstrainedNegationTuples extends AbstractTuples {
 
-  protected static Category logger =
-      Category.getInstance(ConstrainedNegationTuples.class.getName());
+  protected static final Logger logger = Logger.getLogger(ConstrainedNegationTuples.class);
 
   /**
    * The constraint these tuples were generated to satisfy.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DefaultRowComparator.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DefaultRowComparator.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DefaultRowComparator.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.Arrays;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.query.TuplesException;
@@ -62,8 +62,7 @@
   /**
    * Description of the Field
    */
-  static Category logger =
-    Category.getInstance(DefaultRowComparator.class.getName());
+  private static final Logger logger = Logger.getLogger(DefaultRowComparator.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DenseLongMatrix.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DenseLongMatrix.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DenseLongMatrix.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -27,7 +27,7 @@
 
 package org.mulgara.store.tuples;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.query.TuplesException;
 
@@ -44,8 +44,7 @@
  */
 public class DenseLongMatrix {
 
-  private final static Category logger =
-      Category.getInstance(DenseLongMatrix.class.getName());
+  private final static Logger logger = Logger.getLogger(DenseLongMatrix.class);
 
   private long[] matrix;
   private int rows;

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DifferenceUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DifferenceUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DifferenceUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
 
 // Third party packages
 import junit.framework.*; // JUnit
-import org.apache.log4j.Category; // Log4J
+import org.apache.log4j.Logger; // Log4J
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -55,6 +55,11 @@
  */
 public class DifferenceUnitTest extends TestCase {
 
+  /**
+   * Logger.
+   */
+  private static final Logger logger = Logger.getLogger(DifferenceUnitTest.class);
+
   /** Test variable. */
   final Variable x = new Variable("x");
 
@@ -74,12 +79,6 @@
   final Variable v = new Variable("v");
 
   /**
-   * Logger.
-   */
-  private Category logger =
-      Category.getInstance(DifferenceUnitTest.class.getName());
-
-  /**
    * Constructs a new test with the given name.
    *
    * @param name the name of the test

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.Collections;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -62,8 +62,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(DistinctTuples.class.getName());
+  private static final Logger logger = Logger.getLogger(DistinctTuples.class);
 
   /**
    * The proposition to filter.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuplesUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuplesUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/DistinctTuplesUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
 
 // Third party packages
 import junit.framework.*;          // JUnit
-import org.apache.log4j.Category;  // Log4J
+import org.apache.log4j.Logger;  // Log4J
 
 // Locally written packages
 import org.mulgara.query.Variable;
@@ -59,8 +59,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(DistinctTuplesUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(DistinctTuplesUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/HavingPredicates.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/HavingPredicates.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/HavingPredicates.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,6 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;    // Apache Log4J
 import org.jrdf.graph.Node;
 
 // Local packages

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/JoinTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/JoinTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/JoinTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -27,7 +27,7 @@
 
 // Java 2 standard packages
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.mulgara.query.TuplesException;
 import org.mulgara.query.Variable;
 
@@ -57,7 +57,7 @@
     /**
      * Logger.
      */
-    protected static Category logger;
+    protected static Logger logger;
 
     /**
      * Version of {@link #operandBinding}} including only columns to the left of

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LimitedTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LimitedTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LimitedTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.store.tuples;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -58,8 +58,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(LimitedTuples.class.getName());
+  private final static Logger logger = Logger.getLogger(LimitedTuples.class);
 
   /**
    * The maximum number of minterms (rows) to allow through.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LiteralTuplesUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LiteralTuplesUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/LiteralTuplesUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;  // Apache Log4J
+import org.apache.log4j.Logger;    // Apache Log4J
 import junit.framework.*;          // JUnit
 
 // Local packages
@@ -65,8 +65,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(LiteralTuplesUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(LiteralTuplesUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OffsetTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OffsetTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OffsetTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.store.tuples;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -58,8 +58,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(OffsetTuples.class.getName());
+  private final static Logger logger = Logger.getLogger(OffsetTuples.class);
 
   /**
    * The maximum number of minterms (rows) to allow through.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjection.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjection.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.*;
 
 // Locally written packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.mulgara.query.TuplesException;
 import org.mulgara.query.Variable;
 
@@ -63,8 +63,7 @@
    * Logger.
    *
    */
-  private final static Category logger =
-      Category.getInstance(OrderedProjection.class.getName());
+  private final static Logger logger = Logger.getLogger(OrderedProjection.class);
 
   /**
    * The proposition to project.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjectionUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjectionUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/OrderedProjectionUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 import junit.framework.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // locally written packages
 import org.mulgara.query.Variable;
@@ -64,8 +64,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(OrderedProjectionUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(OrderedProjectionUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicate.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicate.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicate.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,9 +30,6 @@
 // Java 2 standard packages
 import java.util.*;
 
-// Third party packages
-import org.apache.log4j.Category;    // Apache Log4J
-
 // Local packages
 import org.mulgara.query.TuplesException;
 import org.mulgara.resolver.spi.ResolverSession;

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicateFactory.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicateFactory.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicateFactory.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,9 +30,6 @@
 // Java 2 standard packages
 import java.util.*;
 
-// Third party packages
-import org.apache.log4j.Category;    // Apache Log4J
-
 // Local packages
 import org.mulgara.query.ConstraintHaving;
 import org.mulgara.query.ConstraintNotOccurs;

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicatePrototype.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicatePrototype.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictPredicatePrototype.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,9 +30,6 @@
 // Java 2 standard packages
 import java.util.*;
 
-// Third party packages
-import org.apache.log4j.Category;    // Apache Log4J
-
 // Local packages
 import org.mulgara.query.ConstraintHaving;
 import org.mulgara.query.TuplesException;

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictionTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictionTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/RestrictionTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -28,7 +28,7 @@
 package org.mulgara.store.tuples;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -54,7 +54,7 @@
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
 class RestrictionTuples extends WrappedTuples {
-  private final static Category logger = Category.getInstance(RestrictionTuples.class.getName());
+  private final static Logger logger = Logger.getLogger(RestrictionTuples.class);
 
   protected RestrictPredicate pred;
 

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/TestTuplesUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/TestTuplesUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/TestTuplesUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -32,7 +32,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;  // Apache Log4J
+import org.apache.log4j.Logger;  // Apache Log4J
 import junit.framework.*;          // JUnit
 
 // Local packages
@@ -64,8 +64,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(TestTuplesUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(TestTuplesUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnboundJoinUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnboundJoinUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnboundJoinUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -29,7 +29,7 @@
 
 // Third party packages
 import junit.framework.*; // JUnit
-import org.apache.log4j.Category; // Log4J
+import org.apache.log4j.Logger; // Log4J
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -58,6 +58,11 @@
 public class UnboundJoinUnitTest extends TestCase {
 
   /**
+   * Logger.
+   */
+  private static final Logger logger = Logger.getLogger(UnboundJoinUnitTest.class);
+
+  /**
    * Description of the Field
    */
   final Variable x = new Variable("x");
@@ -88,12 +93,6 @@
   final Variable v = new Variable("v");
 
   /**
-   * Logger.
-   */
-  private Category logger =
-      Category.getInstance(UnboundJoinUnitTest.class.getName());
-
-  /**
    * Constructs a new test with the given name.
    *
    * @param name the name of the test

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnconstrainedTuplesUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnconstrainedTuplesUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnconstrainedTuplesUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import junit.framework.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Test case for {@link UnconstrainedTuplesUnitTest}.
@@ -58,8 +58,7 @@
   /**
    * Logger.
    */
-  private Category logger =
-      Category.getInstance(UnconstrainedTuplesUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(UnconstrainedTuplesUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppend.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppend.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppend.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.TuplesException;
@@ -64,8 +64,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(UnorderedAppend.class.getName());
+  private final static Logger logger = Logger.getLogger(UnorderedAppend.class);
 
   /**
    * The propositions to conjoin.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppendUnitTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppendUnitTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedAppendUnitTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import junit.framework.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // locally written packages
 import org.mulgara.query.Variable;
@@ -62,8 +62,7 @@
    * Logger.
    *
    */
-  private Category logger =
-      Category.getInstance(UnorderedAppendUnitTest.class.getName());
+  private static final Logger logger = Logger.getLogger(UnorderedAppendUnitTest.class);
 
   /**
    * Constructs a new test with the given name.

Modified: branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedProjection.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedProjection.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples/java/org/mulgara/store/tuples/UnorderedProjection.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.*;
 
 // Log4J
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.Cursor;
@@ -65,8 +65,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(UnorderedProjection.class.getName());
+  private final static Logger logger = Logger.getLogger(UnorderedProjection.class);
 
   /**
    * The proposition to project.

Modified: branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/BlockCacheLine.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/BlockCacheLine.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/BlockCacheLine.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,6 +1,6 @@
 package org.mulgara.store.xa;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import java.io.IOException;
 
@@ -47,8 +47,7 @@
   protected int nextTuple;
   protected int tuplesPerBlock;
 
-  private final static Category logger =
-      Category.getInstance(BlockCacheLine.class.getName());
+  private final static Logger logger = Logger.getLogger(BlockCacheLine.class);
 
 
   public BlockCacheLine(BlockFile file,

Modified: branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/CacheLine.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/CacheLine.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/CacheLine.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,6 +1,6 @@
 package org.mulgara.store.xa;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.query.TuplesException;
 
@@ -52,8 +52,7 @@
   public abstract void advance() throws TuplesException;
 
 
-  private final static Category logger =
-      Category.getInstance(CacheLine.class.getName());
+  private final static Logger logger = Logger.getLogger(CacheLine.class);
 
 
   public int getSegmentSize() {

Modified: branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuples.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuples.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuples.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.query.Constraint;
 import org.mulgara.query.Cursor;
@@ -114,8 +114,7 @@
   protected int[] varLookupList;
 
   // Debugging.
-  private final static Category logger =
-      Category.getInstance(HybridTuples.class.getName());
+  private final static Logger logger = Logger.getLogger(HybridTuples.class);
   private Throwable allocated;
   private Throwable closed;
 

Modified: branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuplesTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuplesTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/HybridTuplesTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 // Java 2 standard packages
 import java.util.*;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages.
 import org.mulgara.query.TuplesException;
@@ -73,8 +73,7 @@
   private final static int ODD_LOAD_SIZE = 200000;
   private final static int BF_SMALL_LOAD_SIZE = 10;
   private final static int BF_LARGE_LOAD_SIZE = 100;
-  private final static Category logger =
-      Category.getInstance(HybridTuplesTest.class.getName());
+  private final static Logger logger = Logger.getLogger(HybridTuplesTest.class);
   private final static int WIDTH = 3;
   private HybridTuples hybridTuples;
   private RowComparator rowComparator;

Modified: branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/MemoryCacheLine.java
===================================================================
--- branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/MemoryCacheLine.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/tuples-hybrid/java/org/mulgara/store/xa/MemoryCacheLine.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -1,6 +1,6 @@
 package org.mulgara.store.xa;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.query.TuplesException;
 import org.mulgara.store.tuples.DenseLongMatrix;
@@ -36,8 +36,7 @@
   protected int    width;
   private   long[] pivotTuple;
 
-  private final static Category logger =
-      Category.getInstance(MemoryCacheLine.class.getName());
+  private final static Logger logger = Logger.getLogger(MemoryCacheLine.class);
 
 
   public MemoryCacheLine(DenseLongMatrix buffer, int size) {

Copied: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/Assoc1toNMap.java (from rev 722, trunk/src/jar/util/java/org/mulgara/util/Assoc1toNMap.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/Assoc1toNMap.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/Assoc1toNMap.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,102 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.rosenlaw.com/OSL3.0.htm
+ *
+ * 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.
+ *
+ * This file is an original work developed by Netymon Pty Ltd
+ * (http://www.netymon.com, mailto:mail at netymon.com) under contract to 
+ * Topaz Foundation. Portions created under this contract are
+ * Copyright (c) 2007 Topaz Foundation
+ * All Rights Reserved.
+ */
+
+package org.mulgara.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A 1:N Associative Map.
+ *
+ * @created 2007-11-12
+ *
+ * @author <a href="mailto:andrae at netymon.com">Andrae Muys</a>
+ *
+ * @company <A href="mailto:mail at netymon.com">Netymon Pty Ltd</A>
+ *
+ * @copyright &copy;2007 <a href="http://www.topazproject.org/">Topaz Project</a>
+ *
+ * @licence Open Software License v3.0</a>
+ */
+
+public class Assoc1toNMap<T1,T2> implements Iterable<Map.Entry<T1,Set<T2>>> {
+  private Map<T1, Set<T2>> map1toN;
+  private Map<T2, T1> mapNto1;
+
+  public Assoc1toNMap() {
+    map1toN = new HashMap<T1, Set<T2>>();
+    mapNto1 = new HashMap<T2, T1>();
+  }
+
+  public T1 get1(T2 t2) {
+    return mapNto1.get(t2);
+  }
+
+  public Set<T2> getN(T1 t1) {
+    return map1toN.get(t1);
+  }
+
+  public void put(T1 t1, T2 t2) {
+    Set<T2> t2set = getN(t1);
+    if (t2set == null) {
+      t2set = new HashSet<T2>();
+      map1toN.put(t1, t2set);
+    }
+    t2set.add(t2);
+    
+    mapNto1.put(t2, t1);
+  }
+
+  public void remove1(T1 t1) {
+    Set<T2> t2set = map1toN.remove(t1);
+    for (T2 t2 : t2set) {
+      mapNto1.remove(t2);
+    }
+  }
+
+  public void removeN(T2 t2) {
+    T1 t1 = mapNto1.remove(t2);
+    if (t1 != null) {
+      Set<T2> t2set = map1toN.get(t1);
+      t2set.remove(t2);
+      if (t2set.isEmpty()) {
+        map1toN.remove(t1);
+      }
+    }
+  }
+
+  public boolean contains1(T1 t1) {
+    return map1toN.containsKey(t1);
+  }
+
+  public boolean containsN(T2 t2) {
+    return mapNto1.containsKey(t2);
+  }
+
+  public Set<T1> getKeySet() {
+    return map1toN.keySet();
+  }
+
+  public Iterator<Map.Entry<T1,Set<T2>>> iterator() {
+    return map1toN.entrySet().iterator();
+  }
+}

Copied: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriber.java (from rev 722, trunk/src/jar/util/java/org/mulgara/util/ClassDescriber.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriber.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriber.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,51 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+package org.mulgara.util;
+
+/**
+ * This class takes a {@link java.lang.Class} or an instance of a class, and describes it
+ * in a format that is serialized as a string.
+ *
+ * @created Mar 28, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public interface ClassDescriber {
+
+  /**
+   * Gets a description of the current class. This is equivalent to calling getDescription(0)
+   * @return A string encoding the description.
+   */
+  public String getDescription();
+
+  /**
+   * Gets a description of the current class, increasing any indenting of the string format if
+   * an indented format is used.
+   * @param indentLevel The number of indents to add to the formatting of the string. Ignored
+   *        if the output string is not in an indented format.
+   * @return A string encoding the description, with indenting increased by indentLevel if relevant.
+   */
+  public String getDescription(int indentLevel);
+
+  /**
+   * Gets the class that is described by this object.
+   * @return The class that this object is describing.
+   */
+  public Class<?> getDescribedClass();
+
+  /**
+   * Sets the size of indenting in the output, if this is relevant to the describer.
+   * @param spaces The size of the indent, in number of spaces.
+   */
+  public void setSpacesPerIndent(int spaces);
+}
\ No newline at end of file

Copied: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriberXML.java (from rev 722, trunk/src/jar/util/java/org/mulgara/util/ClassDescriberXML.java)
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriberXML.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ClassDescriberXML.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -0,0 +1,386 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.util;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+
+/**
+ * This class takes a {@link java.lang.Class} or an instance of a class, and describes it
+ * in XML, with pretty-print indenting.
+ *
+ * @created Mar 28, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class ClassDescriberXML implements ClassDescriber {
+
+  /** The default number of spaces for each new level of indenting. */
+  private static final int DEFAULT_INDENT_SPACES = 2;
+
+  /** The number of spaces to use for each new level of indenting. */
+  private int indentSpaces = DEFAULT_INDENT_SPACES;
+
+  /** The class to be described. */
+  private Class<?> cls;
+
+  /** A string of spaces to use for indenting. The number of spaces should be {@link #indentLevel}*{@link #indentSpaces}. */
+  private String indent;
+
+  /**
+   * Holds the level of indenting to use at a particular moment during XML generation.
+   * Each change only increments or decrements by 1.
+   */
+  private int indentLevel;
+
+  /** A string builder to accumulate the XML as it gets built. */
+  private StringBuilder buffer;
+
+  /**
+   * Creates a describer for the class of an object instance.
+   * @param obj The object instance to get the class description for.
+   */
+  public ClassDescriberXML(Object obj) {
+    this(obj.getClass());
+  }
+
+  /**
+   * Creates a describer for a given class.
+   * @param cls The class tobe described.
+   */
+  public ClassDescriberXML(Class<?> cls) {
+    this.cls = cls;
+  }
+
+  /** @see org.mulgara.util.ClassDescriber#getDescribedClass() */
+  public Class<?> getDescribedClass() {
+    return cls;
+  }
+
+  /**
+   * @see org.mulgara.util.ClassDescriber#getDescription()
+   * @return a String containing XML describing the provided class.
+   */
+  public String getDescription() {
+    setIndent(0);
+    buffer = new StringBuilder();
+    describeClass();
+    return buffer.toString();
+  }
+
+  /**
+   * @see org.mulgara.util.ClassDescriber#getDescription(int)
+   * @param indentLevel The level of indenting to start with.
+   * @return a String containing XML describing the provided class.
+   */
+  public String getDescription(int indentLevel) {
+    setIndent(indentLevel);
+    buffer = new StringBuilder();
+    describeClass();
+    return buffer.toString();
+  }
+
+  /** @see org.mulgara.util.ClassDescriber#setSpacesPerIndent(int) */
+  public void setSpacesPerIndent(int spaces) {
+    indentSpaces = spaces;
+  }
+
+  /**
+   * This method manages the work of describing a class. It calls the desciption methods for
+   * all the parts of a class in order, and wraps the result in a &lt;class&gt; element. The
+   * entire description is appended to {@link #buffer}.
+   * @return The {@link #buffer} containing a full description of the configured class.
+   */
+  private StringBuilder describeClass() {
+    buffer.append(indent).append("<class name=\"").append(cls.getName()).append(">\n");
+    pushIndent();
+    describeSuperClass();
+    describeInterfaces();
+    describeAnnotations();
+    describeFields();
+    describeConstructors();
+    describeMethods();
+    popIndent();
+    buffer.append(indent).append("</class>\n");
+    return buffer;
+  }
+
+  /**
+   * Appends the superclass description of the configured class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeSuperClass() {
+    Class<?> s = cls.getSuperclass();
+    if (s != null) {
+      buffer.append(indent).append("<superclass name=\"").append(s.getName()).append("\"/>\n");
+    }
+    return buffer;
+  }
+
+  /**
+   * Appends the interface descriptions of the current class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeInterfaces() {
+    Class<?>[] classes = cls.getInterfaces();
+    if (classes.length != 0) {
+      buffer.append(indent).append("<interfaces>\n");
+      for (Class<?> c: classes) {
+        buffer.append(indent).append("  <interface name=\"").append(c.getName()).append("\"/>\n");
+      }
+      buffer.append(indent).append("</interfaces>\n");
+    }
+    return buffer;
+  }
+
+  /**
+   * Appends the annotation descriptions of the current class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeAnnotations() {
+    Annotation[] annotations = cls.getAnnotations();
+    addAnnotations(annotations);
+    return buffer;
+  }
+
+  /**
+   * Appends the full field descriptions of the current class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeFields() {
+    Field[] fields = cls.getFields();
+    if (fields.length != 0) {
+      buffer.append(indent).append("<fields>\n");
+      pushIndent();
+      for (Field f: fields) {
+        buffer.append(indent).append("<field name=\"").append(f.getName());
+        buffer.append("\" type=\"").append(f.getType().getName());
+        Annotation[] annotations = f.getDeclaredAnnotations();
+        if (annotations.length == 0) buffer.append("\"/>\n");
+        else {
+          buffer.append("\">\n");
+          pushIndent();
+          addAnnotations(annotations);
+          popIndent();
+          buffer.append(indent).append("</field>\n");
+        }
+      }
+      popIndent();
+      buffer.append(indent).append("</fields>\n");
+    }
+    return buffer;
+  }
+
+  /**
+   * Appends the constructor descriptions of the current class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeConstructors() {
+    Constructor<?>[] constructors = cls.getConstructors();
+    if (constructors.length != 0) {
+      buffer.append(indent).append("<constructors>\n");
+      pushIndent();
+      for (Constructor<?> c: constructors) {
+        buffer.append(indent).append("<constructor");
+        if (c.isVarArgs()) buffer.append(" varargs=\"true\"");
+        if (c.isSynthetic()) buffer.append(" synthethic=\"true\"");
+
+        Class<?>[] exceptions = c.getExceptionTypes();
+        Class<?>[] params = c.getParameterTypes();
+        Annotation[] annotations = c.getDeclaredAnnotations();
+
+        if (params.length == 0 && exceptions.length == 0 && annotations.length == 0) buffer.append("/>\n");
+        else {
+          buffer.append(">\n");
+          pushIndent();
+          addExceptions(exceptions);
+          addAnnotations(annotations);
+          addParameters(params, c.getParameterAnnotations());
+          popIndent();
+        }
+        buffer.append(indent).append("</constructor>\n");
+      }
+      popIndent();
+      buffer.append(indent).append("</constructors>\n");
+    }
+    return buffer;
+  }
+
+  /**
+   * Appends the method descriptions of the current class to {@link #buffer}.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder describeMethods() {
+    Method[] methods = cls.getMethods();
+    if (methods.length != 0) {
+      buffer.append(indent).append("<methods>\n");
+      pushIndent();
+      for (Method m: methods) {
+        buffer.append(indent).append("<method name=\"").append(m.getName()).append("\"");
+        if (m.isVarArgs()) buffer.append(" varargs=\"true\"");
+        if (m.isSynthetic()) buffer.append(" synthethic=\"true\"");
+        if (m.isBridge()) buffer.append(" bridge=\"true\"");
+        buffer.append(">\n");
+        pushIndent();
+
+        Class<?>[] exceptions = m.getExceptionTypes();
+        Class<?>[] params = m.getParameterTypes();
+        Annotation[] annotations = m.getDeclaredAnnotations();
+
+        addExceptions(exceptions);
+        addAnnotations(annotations);
+        addParameters(params, m.getParameterAnnotations());
+        Class<?> ret = m.getReturnType();
+        buffer.append(indent).append("<return ");
+
+        if (ret == null) buffer.append("void=\"true\"/>\n");
+        else buffer.append("type=\"").append(ret.getName()).append("\"/>\n");
+
+        popIndent();
+        buffer.append(indent).append("</method>\n");
+      }
+      popIndent();
+      buffer.append(indent).append("</methods>\n");
+    }
+    return buffer;
+  }
+
+  /**
+   * Appends the annotation descriptions for a given set of annotations to {@link #buffer}.
+   * @param annotations The annotations to obtain descriptions for.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder addAnnotations(Annotation[] annotations) {
+    if (annotations.length == 0) return buffer;
+    buffer.append(indent).append("<annotations>\n");
+    pushIndent();
+    for (Annotation a: annotations) {
+      buffer.append(indent).append("<annotation type=\"").append(a.annotationType().getName()).append("\">");
+      buffer.append(xmlEscape(a.toString())).append("</annotation>\n");
+    }
+    popIndent();
+    buffer.append(indent).append("</annotations>\n");
+    return buffer;
+  }
+
+  /**
+   * Appends the exception descriptions for a given set of exceptions to {@link #buffer}.
+   * @param exceptions The exceptions to obtain descriptions for.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder addExceptions(Class<?>[] exceptions) {
+    if (exceptions.length == 0) return buffer;
+    buffer.append(indent).append("<throws>\n");
+    pushIndent();
+    for (int n = 0; n < exceptions.length; n++) {
+      Class<?> e = exceptions[n];
+      buffer.append(indent).append("<exception type=\"").append(e.getName()).append("\"/>\n");
+    }
+    popIndent();
+    buffer.append(indent).append("</throws>\n");
+    return buffer;
+  }
+
+  /**
+   * Appends the parameter descriptions for a given set of method parameters to {@link #buffer}.
+   * @param params The classes for each parameter.
+   * @param paramAnnotations An array of parameter annotations for each parameter.
+   * @return The updated {@link #buffer}.
+   */
+  private StringBuilder addParameters(Class<?>[] params, Annotation[][] paramAnnotations) {
+    if (params.length == 0) return buffer;
+    for (int nParam = 0; nParam < params.length; nParam++) {
+      Class<?> param = params[nParam];
+      Annotation[] pAnn = paramAnnotations[nParam];
+      buffer.append(indent).append("<parameter type=\"").append(param.getName());
+      if (pAnn.length == 0) buffer.append("\"/>\n");
+      else {
+        buffer.append("\">\n");
+        pushIndent();
+        addAnnotations(pAnn);
+        popIndent();
+        buffer.append(indent).append("</parameter>\n");
+      }
+    }
+    return buffer;
+  }
+
+  /**
+   * Changes the indent level to a new value. The new value is multiplied by the
+   * {@link #indentSpaces} value to get the number of spaces to indent each line by.
+   * @param level The new level to set the indent to. Should be +1 or -1 from the previous value.
+   */
+  private void setIndent(int level) {
+    indentLevel = level;
+    indent = indent(indentLevel);
+  }
+
+  /** Increment the current level of indenting. */
+  private void pushIndent() {
+    indent = indent(++indentLevel);
+  }
+
+  /** Decrement the current level of indenting. */
+  private void popIndent() {
+    indent = indent(--indentLevel);
+  }
+
+  /**
+   * Build a new string containing the number of spaces needed for the current level of indenting.
+   * @param i The indent level to calculate the new indent string for.
+   * @return A new string containing i * {@link #indentSpaces} spaces.
+   */
+  private String indent(int i) {
+    char[] arr = new char[indentSpaces * i];
+    Arrays.fill(arr, ' ');
+    return new String(arr);
+  }
+
+  /** An internal structure for mapping characters disallowed in XML to their escape codes. */
+  private static final Map<Character,String> escapes = new HashMap<Character,String>();
+  static {
+    escapes.put('&', "&amp;");
+    escapes.put('<', "&lt;");
+    escapes.put('\r', "&#13;");
+    escapes.put('>', "&gt;");
+    escapes.put('"', "&quot;");
+    escapes.put('\'', "&apos;");
+  }
+
+  /**
+   * Search for disallowed XML characters in a string, and replace them with their escape codes.
+   * @param s The string to escape.
+   * @return A new version of the input string, with XML escaping done.
+   */
+  private static String xmlEscape(String s) {
+    StringBuilder result = null;
+    for(int i = 0, max = s.length(), delta = 0; i < max; i++) {
+      char c = s.charAt(i);
+      String escCode = escapes.get(c);
+
+      if (escCode != null) {
+        if (result == null) result = new StringBuilder(s);
+        result.replace(i + delta, i + delta + 1, escCode);
+        delta += (escCode.length() - 1);
+      }
+    }
+    return (result == null) ? s : result.toString();
+  }
+
+}

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/IntFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/IntFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/IntFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * A file consisting of longs, ints or bytes that can be accessed concurrently
@@ -64,8 +64,7 @@
   protected final static long MASK32 = 0xffffffffL;
   protected final static ByteOrder byteOrder; // The byte order to use.
 
-  private static Category logger =
-      Category.getInstance(IntFile.class.getName());
+  private static final Logger logger = Logger.getLogger(IntFile.class);
 
   static {
     String useByteOrderProp = System.getProperty("mulgara.xa.useByteOrder");

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/LongToStringMap.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/LongToStringMap.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/LongToStringMap.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.util.TempDir;
 
@@ -58,8 +58,7 @@
 public final class LongToStringMap {
 
   /** Logger for this class */
-  private static Category logger =
-      Category.getInstance(LongToStringMap.class.getName());
+  private static final Logger logger = Logger.getLogger(LongToStringMap.class);
 
   /** File used to store mappings */
   private File stringFileName = null;

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/MappedIntFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/MappedIntFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/MappedIntFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * @created 2003-01-09
@@ -55,8 +55,7 @@
  */
 public final class MappedIntFile extends IntFile {
 
-  private static Category logger =
-      Category.getInstance(MappedIntFile.class.getName());
+  private static final Logger logger = Logger.getLogger(MappedIntFile.class);
 
   private final static long REGION_SIZE_B = 8 * 1024 * 1024;
   private final static long REGION_SIZE_I = REGION_SIZE_B / SIZEOF_INT;

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ResultSetMetaDataImpl.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ResultSetMetaDataImpl.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/ResultSetMetaDataImpl.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.Serializable;
 import java.sql.*;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Log4J
 
@@ -73,8 +73,7 @@
    * Logger.
    *
    */
-  private static Category logger =
-      Category.getInstance(ResultSetMetaDataImpl.class.getName());
+  private static final Logger logger = Logger.getLogger(ResultSetMetaDataImpl.class);
 
   /**
    * The names of the columns.

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/StringToLongMap.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/StringToLongMap.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/StringToLongMap.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.util.LinkedHashMap;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.util.TempDir;
 
@@ -64,8 +64,7 @@
  */
 public final class StringToLongMap {
 
-  private static Category logger =
-      Category.getInstance(StringToLongMap.class.getName());
+  private static final Logger logger = Logger.getLogger(StringToLongMap.class);
 
   // Hash bucket format (16 bytes):
   // [ hash code (4)      ][ string offset (4)  ]

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TempDir.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TempDir.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TempDir.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 
 /**
@@ -58,8 +58,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(TempDir.class.getName());
+  private final static Logger logger = Logger.getLogger(TempDir.class);
 
   private static final File systemTempDir =
       new File(System.getProperty("java.io.tmpdir"));

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSet.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSet.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSet.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Log4J
 
@@ -75,8 +75,7 @@
   /**
    * Logger.
    */
-  private static Category logger =
-      Category.getInstance(TestResultSet.class.getName());
+  private static final Logger logger = Logger.getLogger(TestResultSet.class);
 
   /**
    * The metadata for this result set.

Modified: branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSetTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSetTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util/java/org/mulgara/util/TestResultSetTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // JUnit
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Log4J
 
@@ -58,8 +58,7 @@
    * Logger. Named after the class.
    *
    */
-  private Category logger =
-      Category.getInstance(TestResultSetTest.class.getName());
+  private static final Logger logger = Logger.getLogger(TestResultSetTest.class);
 
   /**
    * Test object.

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -68,8 +68,7 @@
 public final class AVLFile {
 
   /** Logger.  */
-  private final static Category logger =
-      Category.getInstance(AVLFile.class.getName());
+  private final static Logger logger = Logger.getLogger(AVLFile.class);
 
   /** The underlying block file */
   private ManagedBlockFile avlBlockFile;

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFileTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFileTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLFileTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -64,8 +64,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(AVLFileTest.class.getName());
+  private final static Logger logger = Logger.getLogger(AVLFileTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLNode.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLNode.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AVLNode.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.io.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -92,8 +92,7 @@
   final static long NULL_NODE = Block.INVALID_BLOCK_ID;
 
   /** The logger. */
-  private final static Category logger =
-      Category.getInstance(AVLNode.class.getName());
+  private final static Logger logger = Logger.getLogger(AVLNode.class);
 
   /** The most recent phase that this node belongs to. */
   private AVLFile.Phase phase;

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AbstractBlockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AbstractBlockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/AbstractBlockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * An abstract class that represents a file which consists of a number of
@@ -67,8 +67,7 @@
   public final static ByteOrder byteOrder;
 
   /** The logger. */
-  private final static Category logger =
-      Category.getInstance(AbstractBlockFile.class.getName());
+  private final static Logger logger = Logger.getLogger(AbstractBlockFile.class);
 
   /** All the open files accessed as block files. */
   private static Set openFiles = new HashSet();

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/Block.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/Block.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/Block.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,10 +30,9 @@
 // Java 2 standard packages
 import java.io.*;
 import java.nio.*;
-import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -63,8 +62,8 @@
 
   public static final long INVALID_BLOCK_ID = -1;
 
-  private final static Category logger =
-      Category.getInstance(Block.class.getName());
+  @SuppressWarnings("unused")
+  private final static Logger logger = Logger.getLogger(Block.class);
 
   /**
    * The pool of currently unused blocks.  Blocks come from here where possible,
@@ -276,13 +275,30 @@
   public void get(int offset, ByteBuffer byteBuffer) {
     assert offset + byteBuffer.remaining() <= blockSize;
 
-    int start = byteOffset + offset;
-    while (byteBuffer.hasRemaining()) {
-      byteBuffer.put(bb.get(start++));
-    }
+    ByteBuffer src = bb.asReadOnlyBuffer();
+    int pos = byteOffset + offset;
+    src.position(pos);
+    src.limit(pos + byteBuffer.remaining());
+    byteBuffer.put(src);
   }
 
   /**
+   * Gets a read-only portion of the buffer.
+   *
+   * @param offset The location of the required buffer within the data block.
+   * @param size The size of the slice to retrieve.
+   * @return The read only portion of the buffer desired.
+   */
+  public ByteBuffer getSlice(int offset, int size) {
+    assert offset + size <= blockSize;
+
+    ByteBuffer data = bb.asReadOnlyBuffer();
+    data.position(byteOffset + offset);
+    data.limit(byteOffset + offset + size);
+    return data.slice();
+  }
+
+  /**
    * Gets an array of integers from the buffer.
    *
    * @param offset The integer offset to get the data from.

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * This interface provides access to files using {@link Block}s of data which are
@@ -224,8 +224,7 @@
     /**
      * Logger.
      */
-    private final static Category logger =
-        Category.getInstance(IOType.class.getName());
+    private final static Logger logger = Logger.getLogger(IOType.class);
 
     /** Calculate the automatic and default IO types. */
     static {

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFileTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFileTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/BlockFileTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 // Java 2 standard packages
 import java.util.*;
 
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * Test cases for BlockFile.
@@ -88,8 +88,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(BlockFileTest.class.getName());
+  private final static Logger logger = Logger.getLogger(BlockFileTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeList.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeList.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeList.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -36,7 +36,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 import org.mulgara.util.IntFile;
 
 /**
@@ -66,8 +66,7 @@
 public final class FreeList {
 
   /** Logger. */
-  private final static Category logger =
-      Category.getInstance(FreeList.class.getName());
+  private final static Logger logger = Logger.getLogger(FreeList.class);
 
   /** Flag used to indicate that the runtime is in debug mode. */
   private final static boolean DEBUG = false;

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeListTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeListTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/FreeListTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -73,8 +73,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(FreeListTest.class.getName());
+  private final static Logger logger = Logger.getLogger(FreeListTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -35,7 +35,7 @@
 import java.util.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * An implementation of BlockFile which uses regular (position/read/write) file
@@ -61,8 +61,7 @@
 public final class IOBlockFile extends AbstractBlockFile {
 
   /** Logger. */
-  private final static Category logger =
-      Category.getInstance(IOBlockFile.class.getName());
+  private final static Logger logger = Logger.getLogger(IOBlockFile.class);
 
   private static final int NOMINAL_ALLOCATION_SIZE = 1048576; // in bytes
 

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFileTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFileTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/IOBlockFileTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.util.TempDir;
 
@@ -64,8 +64,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-    Category.getInstance(IOBlockFileTest.class.getName());
+  private final static Logger logger = Logger.getLogger(IOBlockFileTest.class);
 
   private File file;
 

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/LockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/LockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/LockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * A lock file abstraction.
@@ -61,8 +61,7 @@
   /**
    * Logger.
    */
-  private final static Category logger =
-      Category.getInstance(LockFile.class.getName());
+  private final static Logger logger = Logger.getLogger(LockFile.class);
 
   /** The set of lock files that are in use by this JVM. */
   private static final Set internalLocks = new HashSet();

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * A class that implements efficient copy-on-write semantics for a BlockFile.
@@ -60,8 +60,7 @@
 public final class ManagedBlockFile {
 
   /** Logger. */
-  private final static Category logger =
-      Category.getInstance(ManagedBlockFile.class.getName()); // Logger.
+  private final static Logger logger = Logger.getLogger(ManagedBlockFile.class);
 
   /** File extension for the FreeList file. */
   private final static String FREELIST_EXT = "_fl";

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFileTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFileTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ManagedBlockFileTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Local packages
 import org.mulgara.util.Constants;
@@ -115,8 +115,7 @@
    * Logger.
    *
    */
-  private final static Category logger =
-      Category.getInstance(ManagedBlockFileTest.class.getName());
+  private final static Logger logger = Logger.getLogger(ManagedBlockFileTest.class);
 
   /**
    * Description of the Field

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFile.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFile.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFile.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -33,7 +33,7 @@
 import java.nio.channels.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * An implementation of BlockFile which uses memory mapped file IO.
@@ -66,8 +66,7 @@
   public final static long REGION_SIZE = 8 * 1024 * 1024;
 
   /** The logger. */
-  private final static Category logger =
-      Category.getInstance(MappedBlockFile.class.getName());
+  private final static Logger logger = Logger.getLogger(MappedBlockFile.class);
 
   /**
    * The system page size. The offset into a file that a mapped region starts

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFileTest.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFileTest.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/MappedBlockFileTest.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -34,7 +34,7 @@
 
 // Third party packages
 import junit.framework.*;
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 import org.mulgara.util.TempDir;
 
@@ -65,8 +65,7 @@
    * Logger.
    *
    */
-  private final static Category logger =
-      Category.getInstance(MappedBlockFileTest.class.getName());
+  private final static Logger logger = Logger.getLogger(MappedBlockFileTest.class);
 
   /**
    * Named constructor.

Modified: branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ObjectPool.java
===================================================================
--- branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ObjectPool.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/jar/util-xa/java/org/mulgara/store/xa/ObjectPool.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -31,7 +31,7 @@
 import java.util.*; // Third party packages
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 /**
  * A pool of objects to avoid calling constructors unnecessarily.
@@ -94,8 +94,7 @@
   public final static int TYPE_S_BLOCK = 0;
 
   /** Logger */
-  private final static Category logger =
-      Category.getInstance(ObjectPool.class.getName());
+  private final static Logger logger = Logger.getLogger(ObjectPool.class);
 
   /** The next cascaded object pool (the root pool) */
   private ObjectPool nextPool;

Modified: branches/mgr-61-sparql/src/war/server-http/java/HttpServer.java
===================================================================
--- branches/mgr-61-sparql/src/war/server-http/java/HttpServer.java	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/war/server-http/java/HttpServer.java	2008-03-28 22:55:51 UTC (rev 723)
@@ -30,7 +30,7 @@
 import java.net.*;
 
 // Third party packages
-import org.apache.log4j.Category;
+import org.apache.log4j.Logger;
 
 // Locally written packages
 import org.mulgara.query.*;
@@ -62,8 +62,7 @@
   /**
    * Logger. This is named after the classname.
    */
-  private final static Category logger =
-    Category.getInstance(HttpServer.class.getName());
+  private final static Logger logger = Logger.getLogger(HttpServer.class);
 
   //
   // Constructor

Modified: branches/mgr-61-sparql/src/war/web-services/WEB-INF/server-config.wsdd
===================================================================
--- branches/mgr-61-sparql/src/war/web-services/WEB-INF/server-config.wsdd	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/src/war/web-services/WEB-INF/server-config.wsdd	2008-03-28 22:55:51 UTC (rev 723)
@@ -8,6 +8,7 @@
   <parameter name="sendMultiRefs" value="true"/>
   <parameter name="sendXMLDeclaration" value="true"/>
   <parameter name="axis.sendMinimizedElements" value="true"/>
+  <parameter name="dotNetSoapEncFix" value="true"/>
   <requestFlow>
    <handler type="java:org.apache.axis.handlers.JWSHandler">
     <parameter name="scope" value="session"/>

Modified: branches/mgr-61-sparql/webdocs.xml
===================================================================
--- branches/mgr-61-sparql/webdocs.xml	2008-03-28 21:34:45 UTC (rev 722)
+++ branches/mgr-61-sparql/webdocs.xml	2008-03-28 22:55:51 UTC (rev 723)
@@ -11,8 +11,15 @@
     <echo message="help:  This message."/>
   </target>
 
+  <target name="-webpage-includes-uptodate">
+    <uptodate property="webpage-includes-uptodate">
+      <srcfiles dir="${template.src.docs.dir}"/>
+      <globmapper from="*" to="${src.docs.dir}/*"/>
+    </uptodate>
+  </target>
 
-  <target name="webpage-includes" description="Creates the webpages directory and does the includes">
+  <target name="webpage-includes" description="Creates the webpages directory and does the includes"
+      depends="-webpage-includes-uptodate" unless="webpage-includes-uptodate">
     <copy todir="${src.docs.dir}">
       <fileset dir="${template.src.docs.dir}"/>
     </copy>




More information about the Mulgara-svn mailing list