Author: bcarothers
Date: 2009-07-20 08:18:58 -0400 (Mon, 20 Jul 2009)
New Revision: 1115
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
trunk/dna-integration-tests/src/test/resources/tck/jpa/
trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
trunk/dna-integration-tests/pom.xml
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java
trunk/dna-integration-tests/src/test/resources/log4j.properties
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java
trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
Log:
DNA-486 Add integration test that uses the JPA connector
Applied patch that fixes a number of minor issues with the JPA connector, adds additional
testing of the move operation for writable connectors, cleans up the TCK integration
tests, and adds a TCK integration test for the JPA connector.
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -0,0 +1,36 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * Unless otherwise indicated, all code in JBoss DNA is licensed
+ * to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.graph;
+
+
+/**
+ * A lexicon of internal and implementation-specific information
+ */
+public class DnaIntLexicon {
+
+ public static class Namespace {
+ public static final String URI =
"http://www.jboss.org/dna/internal/1.0";
+ public static final String PREFIX = "dnaint";
+ }
+}
Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/DnaIntLexicon.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java 2009-07-17
19:12:26 UTC (rev 1114)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -327,6 +327,7 @@
namespaceRegistry.register(JcrMixLexicon.Namespace.PREFIX,
JcrMixLexicon.Namespace.URI);
namespaceRegistry.register(JcrNtLexicon.Namespace.PREFIX,
JcrNtLexicon.Namespace.URI);
namespaceRegistry.register(DnaLexicon.Namespace.PREFIX,
DnaLexicon.Namespace.URI);
+ namespaceRegistry.register(DnaIntLexicon.Namespace.PREFIX,
DnaIntLexicon.Namespace.URI);
// namespaceRegistry.register("dnadtd",
"http://www.jboss.org/dna/dtd/1.0");
// namespaceRegistry.register("dnaxml",
"http://www.jboss.org/dna/xml/1.0");
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/map/AbstractMapWorkspace.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -357,6 +357,13 @@
assert this.getRoot().equals(node) != true;
MapNode oldParent = node.getParent();
Name oldName = node.getName().getName();
+
+ if (this.equals(newAbstractMapWorkspace) &&
node.getParent().getUuid().equals(newParent.getUuid())
+ && node.equals(beforeNode)) {
+ // Trivial move of a node to its parent before itself
+ return;
+ }
+
if (oldParent != null) {
boolean removed = oldParent.getChildren().remove(node);
assert removed == true;
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/WritableConnectorTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -1055,6 +1055,46 @@
}
@Test
+ public void shouldMoveNodeBeforeSibling() {
+
+ String initialPath = "";
+ int depth = 1;
+ int numChildrenPerNode = 3;
+ int numPropertiesPerNode = 3;
+ Stopwatch sw = new Stopwatch();
+ boolean batch = true;
+ createSubgraph(graph, initialPath, depth, numChildrenPerNode,
numPropertiesPerNode, batch, sw, System.out, null);
+
+ // Move last node to front ...
+ graph.move("/node3").before("/node1");
+
+ assertThat(graph.getChildren().of("/"),
hasChildren(segment("node3"), segment("node1"),
segment("node2")));
+
+ // Move last node to front ...
+ graph.move("/node3").before("/node1");
+
+ assertThat(graph.getChildren().of("/"),
hasChildren(segment("node2"), segment("node3"),
segment("node1")));
+
+ }
+
+ @Test
+ public void shouldMoveNodeBeforeSelf() {
+
+ String initialPath = "";
+ int depth = 1;
+ int numChildrenPerNode = 3;
+ int numPropertiesPerNode = 3;
+ Stopwatch sw = new Stopwatch();
+ boolean batch = true;
+ createSubgraph(graph, initialPath, depth, numChildrenPerNode,
numPropertiesPerNode, batch, sw, System.out, null);
+
+ // Move node before itself (trivial change) ...
+ graph.move("/node2").before("/node2");
+
+ assertThat(graph.getChildren().of("/"),
hasChildren(segment("node1"), segment("node2"),
segment("node3")));
+ }
+
+ @Test
public void shouldMoveNodes() {
// Create the tree (at total of 40 nodes, plus the extra 6 added later)...
// /
Modified: trunk/dna-integration-tests/pom.xml
===================================================================
--- trunk/dna-integration-tests/pom.xml 2009-07-17 19:12:26 UTC (rev 1114)
+++ trunk/dna-integration-tests/pom.xml 2009-07-20 12:18:58 UTC (rev 1115)
@@ -75,12 +75,34 @@
<version>${pom.version}</version>
<scope>test</scope>
</dependency>
+
+ <!--
+ JPA Connector Dependencies
+ -->
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-connector-store-jpa</artifactId>
<version>${pom.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>3.4.0.GA</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-c3p0</artifactId>
+ <version>3.3.1.GA</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.2</version>
+ <scope>test</scope>
+ </dependency>
<!--
Logging (require SLF4J API for compiling, but use Log4J and its SLF4J
Added:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
===================================================================
---
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
(rev 0)
+++
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -0,0 +1,80 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.jboss.dna.jcr.DnaRepositoryStub;
+import org.jboss.dna.jcr.DnaTckTest;
+import org.jboss.dna.jcr.JcrTckTest;
+
+/**
+ * Container for the standard integration test suites that should be run against various
read-only and read-write repository
+ * configurations.
+ * <p>
+ * The tests require the repository implementation for the TCK tests to change between
runs. This is accomplished by adding a
+ * {@link ChangeRepositoryTestCase trivial test} to the beginning of the suite that
+ * {@link DnaRepositoryStub#setCurrentConfigurationName(String) changes the repository
configuration} in the
+ * {@link DnaRepositoryStub}.
+ * </p>
+ */
+public abstract class AbstractRepositoryTckTest {
+
+ public static TestSuite readWriteRepositorySuite( final String name ) {
+ TestSuite suite = new TestSuite("Tests for " + name +
"(read-write)");
+ suite.addTest(new ChangeRepositoryTestCase(name));
+ suite.addTest(JcrTckTest.suite());
+ suite.addTestSuite(DnaTckTest.class);
+
+ return suite;
+ }
+
+ public static TestSuite readOnlyRepositorySuite( String name ) {
+ TestSuite suite = new TestSuite("Tests for " + name +
"(read-only)");
+ suite.addTest(new ChangeRepositoryTestCase(name));
+ suite.addTest(JcrTckTest.suite());
+ suite.addTestSuite(DnaTckTest.class);
+
+ return suite;
+ }
+
+ /**
+ * Trivial test case that invokes {@link
DnaRepositoryStub#setCurrentConfigurationName(String)} to change the currently used
+ * TCK configuration. If this test fails, that is an indication that the
configuration is incorrect or that the {@code name}
+ * parameter does not match a valid configuration name.
+ */
+ public static class ChangeRepositoryTestCase extends TestCase {
+ private final String configurationName;
+
+ public ChangeRepositoryTestCase( final String configurationName ) {
+ super("testConfigurationNameChange");
+
+ this.configurationName = configurationName;
+ }
+
+ public void testConfigurationNameChange() {
+ DnaRepositoryStub.setCurrentConfigurationName(configurationName);
+ }
+ }
+}
Property changes on:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/AbstractRepositoryTckTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java
===================================================================
---
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/InfinispanRepositoryTckTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -24,21 +24,9 @@
package org.jboss.dna.test.integration;
import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.dna.jcr.DnaRepositoryStub;
-import org.jboss.dna.jcr.DnaTckTest;
-import org.jboss.dna.jcr.JcrTckTest;
-public class InfinispanRepositoryTckTest extends JcrTckTest {
-
- private static final String NAME = "infinispan";
-
+public class InfinispanRepositoryTckTest {
public static Test suite() {
- DnaRepositoryStub.setCurrentConfigurationName(NAME);
- TestSuite suite = new TestSuite("TCK Tests for " + NAME);
- suite.addTest(JcrTckTest.suite());
- suite.addTestSuite(DnaTckTest.class);
-
- return suite;
+ return
AbstractRepositoryTckTest.readWriteRepositorySuite("infinispan");
}
}
Modified:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java
===================================================================
---
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JBossCacheRepositoryTckTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -24,21 +24,10 @@
package org.jboss.dna.test.integration;
import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.dna.jcr.DnaRepositoryStub;
-import org.jboss.dna.jcr.DnaTckTest;
-import org.jboss.dna.jcr.JcrTckTest;
-public class JBossCacheRepositoryTckTest extends JcrTckTest {
+public class JBossCacheRepositoryTckTest {
- private static final String NAME = "jbosscache";
-
public static Test suite() {
- DnaRepositoryStub.setCurrentConfigurationName(NAME);
- TestSuite suite = new TestSuite("TCK Tests for " + NAME);
- suite.addTest(JcrTckTest.suite());
- suite.addTestSuite(DnaTckTest.class);
-
- return suite;
+ return
AbstractRepositoryTckTest.readWriteRepositorySuite("jbosscache");
}
}
Added:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
===================================================================
---
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
(rev 0)
+++
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -0,0 +1,33 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.test.integration;
+
+import junit.framework.Test;
+
+public class JpaRepositoryTckTest {
+
+ public static Test suite() {
+ return AbstractRepositoryTckTest.readWriteRepositorySuite("jpa");
+ }
+}
Property changes on:
trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/JpaRepositoryTckTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-integration-tests/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-integration-tests/src/test/resources/log4j.properties 2009-07-17 19:12:26
UTC (rev 1114)
+++ trunk/dna-integration-tests/src/test/resources/log4j.properties 2009-07-20 12:18:58
UTC (rev 1115)
@@ -9,8 +9,11 @@
# Set up the default logging to be INFO level, then override specific units
log4j.logger.org.jboss.dna=INFO
-log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
+log4j.logger.org.junit=DEBUG
+#
log4j.logger.org.jboss.dna.tests.integration.jackrabbit.JackrabbitMySqlStressTest=DEBUG
+log4j.logger.org.hibernate=WARN, stdout
+
# Jackrabbit logging
log4j.logger.org.apache.jackrabbit=WARN, stdout
log4j.logger.org.apache.derby=INFO, stdout
Added: trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
===================================================================
--- trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
(rev 0)
+++ trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml 2009-07-20
12:18:58 UTC (rev 1115)
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ JBoss DNA (
http://www.jboss.org/dna)
+ ~
+ ~ See the COPYRIGHT.txt file distributed with this work for information
+ ~ regarding copyright ownership. Some portions may be licensed
+ ~ to Red Hat, Inc. under one or more contributor license agreements.
+ ~ See the AUTHORS.txt file in the distribution for a full listing of
+ ~ individual contributors.
+ ~
+ ~ JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ ~ is licensed to you under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ JBoss DNA is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<configuration
xmlns:dna="http://www.jboss.org/dna/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0">
+ <!--
+ Define the sources for the content. These sources are directly accessible using the
DNA-specific Graph API.
+ In fact, this is how the DNA JCR implementation works. You can think of these as
being similar to
+ JDBC DataSource objects, except that they expose graph content via the Graph API
instead of records via SQL or JDBC.
+ -->
+ <dna:sources jcr:primaryType="nt:unstructured">
+ <!--
+ The 'JCR' repository is a JBoss Cache source with a single default
workspace (though others could be created, too).
+ -->
+ <dna:source jcr:name="Store"
dna:classname="org.jboss.dna.connector.store.jpa.JpaSource"
+ dna:dialect="org.hibernate.dialect.HSQLDialect"
+ dna:driverClassName="org.hsqldb.jdbcDriver"
+ dna:username="sa"
+ dna:password=""
+ dna:url="jdbc:hsqldb:."
+ dna:maximumConnectionsInPool="1"
+ dna:referentialIntegrityEnforced="true"
+ dna:largeValueSizeInBytes="150"
+ dna:retryLimit="3"
+ dna:compressData="true"
+ dna:predefinedWorkspaceNames="default"
+ dna:showSql="false"
+ dna:defaultWorkspaceName="default"/>
+ </dna:sources>
+ <!--
+ Define the mime type detectors. This is an optional section. By default, each engine
will use the
+ MIME type detector that uses filename extensions. So we wouldn't need to define
the same detector again,
+ but this is how you'd define another extension.
+ -->
+ <dna:mimeTypeDetectors>
+ <dna:mimeTypeDetector jcr:name="Detector">
+ <dna:description>Standard extension-based MIME type
detector</dna:description>
+ <!--
+ Specify the implementation class (required), as a child element or attribute
on parent element.
+ -->
+
<dna:classname>org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector</dna:classname>
+ <!--
+ Specify the classpath (optional) as an ordered list of 'names', where
each name is significant to
+ the classpath factory. For example, a name could be an OSGI identifier or a
Maven coordinate,
+ depending upon the classpath factory being used. If there is only one
'name' in the classpath,
+ it may be specified as an attribute on the 'mimeTypeDetector'
element. If there is more than one
+ 'name', then they must be specified as child 'classpath'
elements. Blank or empty values are ignored.
+ -->
+ <dna:classpath></dna:classpath>
+ </dna:mimeTypeDetector>
+ </dna:mimeTypeDetectors>
+ <!--
+ Define the JCR repositories
+ -->
+ <dna:repositories>
+ <!--
+ Define a JCR repository that accesses the 'JCR' source directly.
+ This of course is optional, since we could access the same content through
'JCR'.
+ -->
+ <dna:repository jcr:name="Test Repository Source">
+ <!-- Specify the source that should be used for the repository -->
+ <dna:source>Store</dna:source>
+ <!-- Define the options for the JCR repository, using camelcase version of
JcrRepository.Option names
+-->
+ <dna:options jcr:primaryType="dna:options">
+ <jaasLoginConfigName jcr:primaryType="dna:option"
dna:value="dna-jcr"/>
+ <projectNodeTypes jcr:primaryType="dna:option"
dna:value="false"/>
+ </dna:options>
+ <!-- Define any namespaces for this repository, other than those already
defined by JCR or DNA
+-->
+ <namespaces jcr:primaryType="dna:namespaces">
+ <dnatest jcr:primaryType="dna:namespace"
dna:uri="http://jboss.org/dna/test/1.0"/>
+ </namespaces>
+ </dna:repository>
+ </dna:repositories>
+</configuration>
Property changes on:
trunk/dna-integration-tests/src/test/resources/tck/jpa/configRepository.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Added:
trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties
===================================================================
--- trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties
(rev 0)
+++
trunk/dna-integration-tests/src/test/resources/tck/jpa/repositoryOverlay.properties 2009-07-20
12:18:58 UTC (rev 1115)
@@ -0,0 +1 @@
+# Placeholder for any overlaid properties for this repo configuration
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java 2009-07-17 19:12:26
UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/DnaIntLexicon.java 2009-07-20 12:18:58
UTC (rev 1115)
@@ -29,13 +29,7 @@
/**
* A lexicon of internal and implementation-specific information
*/
-public class DnaIntLexicon {
-
- public static class Namespace {
- public static final String URI =
"http://www.jboss.org/dna/internal/1.0";
- public static final String PREFIX = "dnaint";
- }
-
+public class DnaIntLexicon extends org.jboss.dna.graph.DnaIntLexicon {
public static final Name NODE_DEFINITON = new BasicName(Namespace.URI,
"nodeDefinition");
public static final Name MULTI_VALUED_PROPERTIES = new BasicName(Namespace.URI,
"multiValuedProperties");
}
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-07-17
19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -282,7 +282,7 @@
}
private class SystemViewContentHandler extends DefaultHandler {
- private Stack<AbstractJcrNode> parentStack;
+ private final Stack<AbstractJcrNode> parentStack;
private final String svNameName;
private final String svTypeName;
@@ -292,7 +292,7 @@
private int currentPropType;
private StringBuffer valueBuffer;
- private Map<String, List<Value>> currentProps;
+ private final Map<String, List<Value>> currentProps;
/**
* @param currentNode
@@ -346,6 +346,31 @@
if (rawUuid != null) {
assert rawUuid.size() == 1;
uuid = UUID.fromString(rawUuid.get(0).getString());
+
+ try {
+ // Deal with any existing node ...
+ AbstractJcrNode existingNodeWithUuid =
cache().findJcrNode(Location.create(uuid));
+ switch (uuidBehavior) {
+ case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING:
+ parentNode = existingNodeWithUuid.getParent();
+ existingNodeWithUuid.remove();
+ break;
+ case ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW:
+ uuid = UUID.randomUUID();
+ break;
+ case
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING:
+ if
(existingNodeWithUuid.path().isAtOrAbove(parentStack.firstElement().path())) {
+ throw new ConstraintViolationException();
+ }
+ existingNodeWithUuid.remove();
+ break;
+ case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
+ throw new ItemExistsException();
+ }
+ } catch (ItemNotFoundException e) {
+ // there wasn't an existing item, so just continue
+ }
+
}
String typeName =
currentProps.get(primaryTypeName).get(0).getString();
@@ -427,7 +452,7 @@
}
private class DocumentViewContentHandler extends DefaultHandler {
- private Stack<AbstractJcrNode> parentStack;
+ private final Stack<AbstractJcrNode> parentStack;
/**
* @param currentNode
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-07-17 19:12:26 UTC
(rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrValue.java 2009-07-20 12:18:58 UTC
(rev 1115)
@@ -442,6 +442,11 @@
}
}
+ @Override
+ public String toString() {
+ return (value == null ? "null" : value.toString()) + " (" +
PropertyType.nameFromValue(type) + ")";
+ }
+
private enum State {
NEVER_CONSUMED,
INPUT_STREAM_CONSUMED,
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-07-17 19:12:26
UTC (rev 1114)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java 2009-07-20 12:18:58
UTC (rev 1115)
@@ -139,7 +139,7 @@
protected final Path rootPath;
protected final Name residualName;
- private GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession;
+ private final GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession;
public SessionCache( JcrSession session ) {
this(session, session.workspace().getName(), session.getExecutionContext(),
session.nodeTypeManager(), session.graph());
@@ -1320,6 +1320,7 @@
if
(JcrMixLexicon.REFERENCEABLE.equals(mixinCandidateType.getInternalName())) {
// This node is now referenceable, so make sure there is a UUID
property ...
UUID uuid = node.getLocation().getUuid();
+ if (uuid == null) uuid =
(UUID)node.getLocation().getIdProperty(JcrLexicon.UUID).getFirstValue();
if (uuid == null) uuid = UUID.randomUUID();
JcrValue value = new JcrValue(factories(), SessionCache.this,
PropertyType.STRING, uuid);
setProperty(JcrLexicon.UUID, value, false);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java 2009-07-17
19:12:26 UTC (rev 1114)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/DnaRepositoryStub.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -43,8 +43,10 @@
private static String currentConfigurationName = "default";
- private final Properties configProps;
- private final JcrRepository repository;
+ private Properties configProps;
+ private String repositoryConfigurationName;
+ private JcrRepository repository;
+
static {
@@ -62,15 +64,21 @@
public DnaRepositoryStub( Properties env ) {
super(env);
+ configureRepository();
+ }
+
+ private void configureRepository() {
+ repositoryConfigurationName = currentConfigurationName;
+
// Create the in-memory (DNA) repository
JcrConfiguration configuration = new JcrConfiguration();
try {
configProps = new Properties();
- String propsFileName = "/tck/" + currentConfigurationName +
"/repositoryOverlay.properties";
+ String propsFileName = "/tck/" + repositoryConfigurationName +
"/repositoryOverlay.properties";
InputStream propsStream = getClass().getResourceAsStream(propsFileName);
configProps.load(propsStream);
- String configFileName = "/tck/" + currentConfigurationName +
"/configRepository.xml";
+ String configFileName = "/tck/" + repositoryConfigurationName +
"/configRepository.xml";
configuration.loadFrom(getClass().getResourceAsStream(configFileName));
// Add the the node types for the source ...
@@ -86,8 +94,8 @@
JcrEngine engine = configuration.build();
engine.start();
- // Problems problems = engine.getRepositoryService().getStartupProblems();
- Problems problems = engine.getProblems();
+ Problems problems = engine.getRepositoryService().getStartupProblems();
+ // Problems problems = engine.getProblems();
// Print all of the problems from the engine configuration ...
for (Problem problem : problems) {
System.err.println(problem);
@@ -96,17 +104,11 @@
throw new IllegalStateException("Problems starting JCR
repository");
}
- repository = getAndLoadRepository(engine, REPOSITORY_SOURCE_NAME);
- }
-
- private JcrRepository getAndLoadRepository( JcrEngine engine,
- String repositoryName ) {
-
ExecutionContext executionContext = engine.getExecutionContext();
executionContext.getNamespaceRegistry().register(TestLexicon.Namespace.PREFIX,
TestLexicon.Namespace.URI);
try {
- JcrRepository repository = engine.getRepository(REPOSITORY_SOURCE_NAME);
+ repository = engine.getRepository(REPOSITORY_SOURCE_NAME);
// Set up some sample nodes in the graph to match the expected test
configuration
Graph graph = Graph.create(repository.getRepositorySourceName(),
@@ -118,7 +120,6 @@
graph.importXmlFrom(xmlStream).into(destinationPath);
graph.createWorkspace().named("otherWorkspace");
- return repository;
} catch (Exception ex) {
// The TCK tries to quash this exception. Print it out to be more obvious.
@@ -126,6 +127,7 @@
throw new IllegalStateException("Failed to initialize the repository
with text content.", ex);
}
+
}
public static void setCurrentConfigurationName( String newConfigName ) {
@@ -139,6 +141,9 @@
*/
@Override
public JcrRepository getRepository() {
+ if (!currentConfigurationName.equals(repositoryConfigurationName)) {
+ configureRepository();
+ }
return repository;
}
Modified: trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties
===================================================================
--- trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-07-17 19:12:26 UTC
(rev 1114)
+++ trunk/dna-jcr/src/test/resources/repositoryStubImpl.properties 2009-07-20 12:18:58 UTC
(rev 1115)
@@ -14,7 +14,8 @@
javax.jcr.tck.targetFolderName=target
javax.jcr.tck.rootNodeName=rootNode
javax.jcr.tck.propertySkipped=propertySkipped
-javax.jcr.tck.propertyValueMayChange=propertyValueMayChange
+# The spaces on either side of this property are important - DO NOT DELETE THEM
+javax.jcr.tck.propertyValueMayChange= jcr:uuid
javax.jcr.tck.nodeTypesTestNode=nodeTypesTestNode
javax.jcr.tck.mixinTypeTestNode=mixinTypeTestNode
javax.jcr.tck.propertyTypesTestNode=propertyTypesTestNode
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -142,6 +142,10 @@
*/
public static final boolean DEFAULT_SUPPORTS_UPDATES = true;
/**
+ * This source does not output executed SQL by default, but this can be overridden by
calling {@link #setShowSql(boolean)}.
+ */
+ public static final boolean DEFAULT_SHOW_SQL = false;
+ /**
* This source does support creating workspaces.
*/
public static final boolean DEFAULT_SUPPORTS_CREATING_WORKSPACES = true;
@@ -152,7 +156,7 @@
public static final String DEFAULT_ROOT_NODE_UUID =
"1497b6fe-8c7e-4bbb-aaa2-24f3d4942668";
/**
- * The initial {@link #getNameOfDefaultWorkspace() name of the default workspace} is
"{@value} ", unless otherwise specified.
+ * The initial {@link #getDefaultWorkspaceName() name of the default workspace} is
"{@value} ", unless otherwise specified.
*/
public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default";
@@ -192,6 +196,7 @@
private volatile int retryLimit = DEFAULT_RETRY_LIMIT;
private volatile int cacheTimeToLiveInMilliseconds =
DEFAULT_CACHE_TIME_TO_LIVE_IN_SECONDS * 1000;
private volatile long largeValueSizeInBytes = DEFAULT_LARGE_VALUE_SIZE_IN_BYTES;
+ private volatile boolean showSql = DEFAULT_SHOW_SQL;
private volatile boolean compressData = DEFAULT_COMPRESS_DATA;
private volatile boolean referentialIntegrityEnforced =
DEFAULT_ENFORCE_REFERENTIAL_INTEGRITY;
private volatile String defaultWorkspace = DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
@@ -263,6 +268,24 @@
}
/**
+ * Get whether this source outputs the SQL that it executes
+ *
+ * @return whether this source outputs the SQL that it executes
+ */
+ public boolean getShowSql() {
+ return this.showSql;
+ }
+
+ /**
+ * Sets whether this source should output the SQL that it executes
+ *
+ * @param showSql true if this source should output the SQL that it executes,
otherwise false
+ */
+ public synchronized void setShowSql( boolean showSql ) {
+ this.showSql = showSql;
+ }
+
+ /**
* {@inheritDoc}
*
* @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit()
@@ -324,7 +347,7 @@
*
* @return the name of the workspace that should be used by default, or null if there
is no default workspace
*/
- public String getNameOfDefaultWorkspace() {
+ public String getDefaultWorkspaceName() {
return defaultWorkspace;
}
@@ -334,7 +357,7 @@
* @param nameOfDefaultWorkspace the name of the workspace that should be used by
default, or null if the
* {@link #DEFAULT_NAME_OF_DEFAULT_WORKSPACE default name} should be used
*/
- public synchronized void setNameOfDefaultWorkspace( String nameOfDefaultWorkspace )
{
+ public synchronized void setDefaultWorkspaceName( String nameOfDefaultWorkspace ) {
this.defaultWorkspace = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace :
DEFAULT_NAME_OF_DEFAULT_WORKSPACE;
}
@@ -733,7 +756,7 @@
ref.add(new StringRefAddr(LARGE_VALUE_SIZE_IN_BYTES,
Long.toString(getLargeValueSizeInBytes())));
ref.add(new StringRefAddr(COMPRESS_DATA, Boolean.toString(isCompressData())));
ref.add(new StringRefAddr(ENFORCE_REFERENTIAL_INTEGRITY,
Boolean.toString(isReferentialIntegrityEnforced())));
- ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getNameOfDefaultWorkspace()));
+ ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getDefaultWorkspaceName()));
ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES,
Boolean.toString(isCreatingWorkspacesAllowed())));
String[] workspaceNames = getPredefinedWorkspaceNames();
if (workspaceNames != null && workspaceNames.length != 0) {
@@ -819,7 +842,7 @@
if (largeModelSize != null)
source.setLargeValueSizeInBytes(Long.parseLong(largeModelSize));
if (compressData != null)
source.setCompressData(Boolean.parseBoolean(compressData));
if (refIntegrity != null)
source.setReferentialIntegrityEnforced(Boolean.parseBoolean(refIntegrity));
- if (defaultWorkspace != null)
source.setNameOfDefaultWorkspace(defaultWorkspace);
+ if (defaultWorkspace != null)
source.setDefaultWorkspaceName(defaultWorkspace);
if (createWorkspaces != null)
source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
if (workspaceNames != null && workspaceNames.length != 0)
source.setPredefinedWorkspaceNames(workspaceNames);
return source;
@@ -886,7 +909,7 @@
setProperty(configurator, "hibernate.connection.url",
this.url);
setProperty(configurator,
"hibernate.connection.max_fetch_depth", DEFAULT_MAXIMUM_FETCH_DEPTH);
setProperty(configurator, "hibernate.connection.pool_size", 0);
// don't use the built-in pool
- setProperty(configurator, "hibernate.show_sql",
"false");
+ setProperty(configurator, "hibernate.show_sql",
String.valueOf(this.showSql));
}
entityManagerFactory = configurator.buildEntityManagerFactory();
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/BasicRequestProcessor.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -76,6 +76,7 @@
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.PathNotFoundException;
import org.jboss.dna.graph.property.Property;
+import org.jboss.dna.graph.property.PropertyFactory;
import org.jboss.dna.graph.property.PropertyType;
import org.jboss.dna.graph.property.Reference;
import org.jboss.dna.graph.property.ReferentialIntegrityException;
@@ -116,6 +117,7 @@
protected final EntityManager entities;
protected final ValueFactory<String> stringFactory;
protected final PathFactory pathFactory;
+ protected final PropertyFactory propertyFactory;
protected final NameFactory nameFactory;
protected final UuidFactory uuidFactory;
protected final Namespaces namespaces;
@@ -138,7 +140,7 @@
REPLACE_EXISTING_NODE,
THROW_EXCEPTION
}
-
+
/**
* @param sourceName
* @param context
@@ -171,6 +173,7 @@
ValueFactories valuesFactory = context.getValueFactories();
this.stringFactory = valuesFactory.getStringFactory();
this.pathFactory = valuesFactory.getPathFactory();
+ this.propertyFactory = context.getPropertyFactory();
this.nameFactory = valuesFactory.getNameFactory();
this.uuidFactory = valuesFactory.getUuidFactory();
this.namespaces = new Namespaces(entityManager);
@@ -460,7 +463,9 @@
actualLocation = actual.location;
// Record the UUID as a property, since it's not stored in the serialized
properties...
- request.addProperty(actualLocation.getIdProperty(DnaLexicon.UUID));
+ // This gets pulled from the actual location uuid instead of the property to
avoid the
+ // having to add the dna:uuid onto locations that already have a jcr:uuid
+ request.addProperty(propertyFactory.create(DnaLexicon.UUID,
UUID.fromString(parentUuidString)));
// Find the properties entity for this node ...
Query query =
entities.createNamedQuery("PropertiesEntity.findByUuid");
@@ -828,7 +833,7 @@
// Small optimization ...
final Name propertyName = request.named();
- if (DnaLexicon.UUID.equals(propertyName)) {
+ if (DnaLexicon.UUID.equals(propertyName) ||
JcrLexicon.UUID.equals(propertyName)) {
try {
// Just get the UUID ...
Location location = request.on();
@@ -918,8 +923,16 @@
boolean compressed = entity.isCompressed();
byte[] originalData = entity.getData();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
- ObjectOutputStream oos = new ObjectOutputStream(os);
+ ObjectOutputStream oos;
+ GZIPOutputStream gos = null;
+ if (compressed) {
+ gos = new GZIPOutputStream(baos);
+ oos = new ObjectOutputStream(gos);
+ } else {
+ oos = new ObjectOutputStream(baos);
+ }
+ // OutputStream os = compressed ? new GZIPOutputStream(baos) : baos;
+ // oos = new ObjectOutputStream(os);
int numProps = 0;
LargeValueSerializer largeValues = null;
Map<Name, Property> props = request.properties();
@@ -928,6 +941,7 @@
largeValues = new LargeValueSerializer(entity);
numProps = props.size();
serializer.serializeProperties(oos, numProps, props.values(),
largeValues, refs);
+ if (gos != null) gos.finish();
} else {
boolean hadLargeValues = !entity.getLargeValues().isEmpty();
Set<String> largeValueHashesWritten = hadLargeValues ? new
HashSet<String>() : null;
@@ -939,6 +953,7 @@
try {
Serializer.ReferenceValues refValues = refs != null ? refs :
Serializer.NO_REFERENCES_VALUES;
numProps = serializer.reserializeProperties(ois, oos, props,
largeValues, removedValues, refValues);
+ if (gos != null) gos.finish();
} finally {
try {
ois.close();
@@ -946,6 +961,7 @@
oos.close();
}
}
+
// The new large values were recorded and associated with the
properties entity during reserialization.
// However, any values no longer used now need to be removed ...
if (hadLargeValues) {
@@ -1806,12 +1822,232 @@
}
}
+ private Location moveNodeToLastChild( WorkspaceEntity workspace,
+ ActualLocation actualFromLocation,
+ ActualLocation actualIntoLocation,
+ Name desiredName ) {
+ long workspaceId = workspace.getId();
+ Path oldPath = actualFromLocation.location.getPath();
+
+ ChildEntity fromEntity = actualFromLocation.childEntity;
+
+ // Now we know that the new parent is not the existing parent ...
+ final int oldIndex = fromEntity.getIndexInParent();
+ final String oldParentUuid = fromEntity.getParentUuidString();
+
+ String toUuidString = actualIntoLocation.uuid;
+
+ // Make sure the child name is set correctly ...
+ String childOldLocalName = fromEntity.getChildName();
+ String childLocalName = null;
+ NamespaceEntity ns = null;
+ Name childName = desiredName;
+ if (childName != null) {
+ childLocalName = desiredName.getLocalName();
+ String childNsUri = childName.getNamespaceUri();
+ ns = namespaces.get(childNsUri, true);
+ } else {
+ childName = oldPath.getLastSegment().getName();
+ childLocalName = fromEntity.getChildName();
+ ns = fromEntity.getChildNamespace();
+ }
+
+ int nextSnsIndex = 1;
+ int nextIndexInParent = 1;
+
+ // Find the largest SNS index in the existing ChildEntity objects with the same
name ...
+ Query query =
entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
+ query.setParameter("workspaceId", workspaceId);
+ query.setParameter("parentUuid", toUuidString);
+ query.setParameter("ns", ns.getId());
+ query.setParameter("childName", childLocalName);
+ try {
+ Integer index = (Integer)query.getSingleResult();
+ if (index != null) nextSnsIndex = index.intValue() + 1;
+ } catch (NoResultException e) {
+ }
+
+ // Find the largest child index in the existing ChildEntity objects ...
+ query =
entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
+ query.setParameter("workspaceId", workspaceId);
+ query.setParameter("parentUuid", toUuidString);
+ try {
+ Integer index = (Integer)query.getSingleResult();
+ if (index != null) nextIndexInParent = index + 1;
+ } catch (NoResultException e) {
+ }
+
+ fromEntity.setParentUuidString(toUuidString);
+ fromEntity.setChildName(childLocalName);
+ fromEntity.setChildNamespace(ns);
+ fromEntity.setIndexInParent(nextIndexInParent);
+ fromEntity.setSameNameSiblingIndex(nextSnsIndex);
+
+ // Flush the entities to the database ...
+ entities.flush();
+
+ // Determine the new location ...
+ Path newParentPath = actualIntoLocation.location.getPath();
+ Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
+ Location newLocation = actualFromLocation.location.with(newPath);
+
+ // And adjust the SNS index and indexes ...
+ ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
+ workspaceId,
+ oldParentUuid,
+ childOldLocalName,
+ ns.getId(),
+ oldIndex);
+
+ // Update the cache ...
+ cache.moveNode(workspaceId, actualFromLocation.location, oldIndex, newLocation);
+
+ return newLocation;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ private Location moveNodeBefore( WorkspaceEntity workspace,
+ ActualLocation actualFromLocation,
+ ActualLocation actualIntoLocation,
+ ActualLocation actualBeforeLocation ) {
+
+ long workspaceId = workspace.getId();
+
+ ChildEntity fromEntity = actualFromLocation.childEntity;
+ assert fromEntity != null;
+
+ Path oldPath = actualFromLocation.location.getPath();
+ String oldParentUuid = fromEntity.getParentUuidString();
+
+ String toUuidString = actualIntoLocation.uuid;
+ Location beforeLocation = actualBeforeLocation.location;
+ ChildEntity beforeEntity = actualBeforeLocation.childEntity;
+
+ /*
+ * getActualLocation (which populates actualBeforeLocation) can return null for
the childEntity
+ * if the location was retrieved from the cache. Since we need the beforeEntity,
try to force the load.
+ */
+ if (beforeEntity == null) {
+ beforeEntity = findNode(workspaceId, actualBeforeLocation.uuid);
+ }
+
+ assert beforeEntity != null;
+
+ Name childName = oldPath.getLastSegment().getName();
+ String childLocalName = fromEntity.getChildName();
+ NamespaceEntity ns = fromEntity.getChildNamespace();
+
+ boolean sameParent = oldParentUuid.equals(toUuidString);
+
+ if (sameParent) {
+ int oldIndex;
+ if (fromEntity.getIndexInParent() < beforeEntity.getIndexInParent()) {
+ oldIndex = beforeEntity.getIndexInParent();
+
+ int snsCount = ChildEntity.adjustSnsIndexesAndIndexes(entities,
+ workspaceId,
+
fromEntity.getParentUuidString(),
+
fromEntity.getIndexInParent(),
+
beforeEntity.getIndexInParent(),
+
fromEntity.getChildNamespace().getId(),
+
fromEntity.getChildName(),
+ -1);
+
+ fromEntity.setIndexInParent(oldIndex);
+ fromEntity.setSameNameSiblingIndex(fromEntity.getSameNameSiblingIndex() +
snsCount);
+ } else {
+ oldIndex = beforeEntity.getIndexInParent();
+
+ int snsCount = ChildEntity.adjustSnsIndexesAndIndexes(entities,
+ workspaceId,
+
fromEntity.getParentUuidString(),
+
beforeEntity.getIndexInParent() - 1,
+
fromEntity.getIndexInParent() - 1,
+
fromEntity.getChildNamespace().getId(),
+
fromEntity.getChildName(),
+ +1);
+
+ fromEntity.setIndexInParent(oldIndex);
+ fromEntity.setSameNameSiblingIndex(fromEntity.getSameNameSiblingIndex() -
snsCount);
+
+ }
+
+ Path newPath = pathFactory.create(oldPath.getParent(),
+
pathFactory.createSegment(fromEntity.getChildName(),
+
fromEntity.getSameNameSiblingIndex()));
+ return actualFromLocation.location.with(newPath);
+ }
+
+ int oldIndex = fromEntity.getIndexInParent();
+
+ /*
+ * This is a sub-optimal approach, particularly for inserts to the front
+ * of a long list of child nodes, but it guarantees that we won't have
+ * the JPA-cached entities and the database out of sync.
+ */
+
+ Query query =
entities.createNamedQuery("ChildEntity.findAllUnderParent");
+ query.setParameter("workspaceId", workspaceId);
+ query.setParameter("parentUuidString", toUuidString);
+
+ int nextIndexInParent = 0;
+ int nextSnsIndex = 1;
+ try {
+ List<ChildEntity> children = query.getResultList();
+ Path beforePath = beforeLocation.getPath();
+ Path.Segment beforeSegment = beforePath.getLastSegment();
+
+ boolean foundBefore = false;
+ for (ChildEntity child : children) {
+ NamespaceEntity namespace = child.getChildNamespace();
+ if (namespace.getUri().equals(ns.getUri()) &&
child.getChildName().equals(childLocalName)
+ && child.getSameNameSiblingIndex() ==
beforeSegment.getIndex()) {
+ foundBefore = true;
+ nextIndexInParent = child.getIndexInParent();
+ nextSnsIndex = beforeSegment.getIndex();
+ }
+
+ if (foundBefore) {
+ child.setIndexInParent(child.getIndexInParent() + 1);
+ if (child.getChildName().equals(childLocalName) &&
namespace.getUri().equals(ns.getUri())) {
+ child.setSameNameSiblingIndex(child.getSameNameSiblingIndex() +
1);
+ }
+ entities.persist(child);
+ }
+ }
+
+ } catch (NoResultException e) {
+ }
+
+ fromEntity.setParentUuidString(toUuidString);
+ fromEntity.setChildName(childLocalName);
+ fromEntity.setChildNamespace(ns);
+ fromEntity.setIndexInParent(nextIndexInParent);
+ fromEntity.setSameNameSiblingIndex(nextSnsIndex);
+
+ // Flush the entities to the database ...
+ entities.flush();
+
+ // Determine the new location ...
+ Path newParentPath = actualIntoLocation.location.getPath();
+ Path newPath = pathFactory.create(newParentPath, childName, nextSnsIndex);
+ Location oldLocation = actualFromLocation.location;
+ Location newLocation = oldLocation.with(newPath);
+
+ // And adjust the SNS index and indexes ...
+ ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities, workspaceId,
oldParentUuid, childLocalName, ns.getId(), -1);
+
+ // Update the cache ...
+ cache.moveNode(workspaceId, oldLocation, oldIndex, newLocation);
+
+ return newLocation;
+ }
+
/**
* {@inheritDoc}
*
* @see
org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.MoveBranchRequest)
*/
- @SuppressWarnings( "unchecked" )
@Override
public void process( MoveBranchRequest request ) {
logger.trace(request.toString());
@@ -1835,143 +2071,25 @@
throw new InvalidRequestException(msg);
}
- // Find the ChildEntity of the existing 'from' node ...
- ChildEntity fromEntity = actualLocation.childEntity;
- final String oldParentUuid = fromEntity.getParentUuidString();
-
- // Find the actual new location ...
- Location toLocation = request.into();
- Location beforeLocation = request.before();
-
- if (beforeLocation != null) {
- if (beforeLocation.hasPath()) {
- toLocation = Location.create(beforeLocation.getPath().getParent());
- } else {
- ActualLocation actualBeforeLocation = getActualLocation(workspace,
beforeLocation);
-
- // Ensure that the beforeLocation has a path - actualBeforeLocation
has a path
- beforeLocation = actualBeforeLocation.location;
- toLocation =
Location.create(actualBeforeLocation.location.getPath().getParent());
- }
- }
-
- String toUuidString = null;
if (request.hasNoEffect()) {
actualNewLocation = actualOldLocation;
} else {
// We have to proceed as normal ...
- ActualLocation actualIntoLocation = getActualLocation(workspace,
toLocation);
- toUuidString = actualIntoLocation.uuid;
- if (!toUuidString.equals(oldParentUuid)) {
- // Now we know that the new parent is not the existing parent ...
- final int oldIndex = fromEntity.getIndexInParent();
- // Make sure the child name is set correctly ...
- String childOldLocalName = fromEntity.getChildName();
- String childLocalName = null;
- NamespaceEntity ns = null;
- Name childName = request.desiredName();
- if (childName != null) {
- childLocalName = request.desiredName().getLocalName();
- String childNsUri = childName.getNamespaceUri();
- ns = namespaces.get(childNsUri, true);
- } else {
- childName = oldPath.getLastSegment().getName();
- childLocalName = fromEntity.getChildName();
- ns = fromEntity.getChildNamespace();
- }
+ Location beforeLocation = request.before();
+ if (beforeLocation == null) {
+ ActualLocation actualIntoLocation = getActualLocation(workspace,
request.into());
- int nextSnsIndex = 1;
- int nextIndexInParent = 1;
- if (beforeLocation == null) {
- // Find the largest SNS index in the existing ChildEntity objects
with the same name ...
- Query query =
entities.createNamedQuery("ChildEntity.findMaximumSnsIndex");
- query.setParameter("workspaceId", workspaceId);
- query.setParameter("parentUuid", toUuidString);
- query.setParameter("ns", ns.getId());
- query.setParameter("childName", childLocalName);
- try {
- Integer index = (Integer)query.getSingleResult();
- if (index != null) nextSnsIndex = index.intValue() + 1;
- } catch (NoResultException e) {
- }
+ actualNewLocation = moveNodeToLastChild(workspace, actualLocation,
actualIntoLocation, request.desiredName());
+ } else {
- // Find the largest child index in the existing ChildEntity
objects ...
- query =
entities.createNamedQuery("ChildEntity.findMaximumChildIndex");
- query.setParameter("workspaceId", workspaceId);
- query.setParameter("parentUuid", toUuidString);
- try {
- Integer index = (Integer)query.getSingleResult();
- if (index != null) nextIndexInParent = index + 1;
- } catch (NoResultException e) {
- }
- } else {
- /*
- * This is a sub-optimal approach, particularly for inserts to
the front
- * of a long list of child nodes, but it guarantees that we
won't have
- * the JPA-cached entities and the database out of sync.
- */
+ ActualLocation actualBeforeLocation = getActualLocation(workspace,
beforeLocation);
+ ActualLocation actualIntoLocation = getActualLocation(workspace,
+
Location.create(beforeLocation.getPath().getParent()));
- Query query =
entities.createNamedQuery("ChildEntity.findAllUnderParent");
- query.setParameter("workspaceId", workspaceId);
- query.setParameter("parentUuidString", toUuidString);
- try {
- List<ChildEntity> children = query.getResultList();
- Path beforePath = beforeLocation.getPath();
- Path.Segment beforeSegment = beforePath.getLastSegment();
-
- boolean foundBefore = false;
- for (ChildEntity child : children) {
- NamespaceEntity namespace = child.getChildNamespace();
- if (namespace.getUri().equals(ns.getUri()) &&
child.getChildName().equals(childLocalName)
- && child.getSameNameSiblingIndex() ==
beforeSegment.getIndex()) {
- foundBefore = true;
- nextIndexInParent = child.getIndexInParent();
- nextSnsIndex = beforeSegment.getIndex();
- }
-
- if (foundBefore) {
- child.setIndexInParent(child.getIndexInParent() +
1);
- if (child.getChildName().equals(childLocalName)
&& namespace.getUri().equals(ns.getUri())) {
-
child.setSameNameSiblingIndex(child.getSameNameSiblingIndex() + 1);
- }
- entities.persist(child);
- }
- }
-
- } catch (NoResultException e) {
- }
-
- }
-
- fromEntity.setParentUuidString(toUuidString);
- fromEntity.setChildName(childLocalName);
- fromEntity.setChildNamespace(ns);
- fromEntity.setIndexInParent(nextIndexInParent);
- fromEntity.setSameNameSiblingIndex(nextSnsIndex);
-
- // Flush the entities to the database ...
- entities.flush();
-
- // Determine the new location ...
- Path newParentPath = actualIntoLocation.location.getPath();
- Path newPath = pathFactory.create(newParentPath, childName,
nextSnsIndex);
- actualNewLocation = actualOldLocation.with(newPath);
-
- // And adjust the SNS index and indexes ...
- ChildEntity.adjustSnsIndexesAndIndexesAfterRemoving(entities,
- workspaceId,
- oldParentUuid,
-
childOldLocalName,
- ns.getId(),
- oldIndex);
-
- // Update the cache ...
- cache.moveNode(workspaceId, actualOldLocation, oldIndex,
actualNewLocation);
+ actualNewLocation = moveNodeBefore(workspace, actualLocation,
actualIntoLocation, actualBeforeLocation);
}
-
}
-
} catch (Throwable e) { // Includes PathNotFoundException
System.err.flush();
System.out.flush();
@@ -2311,7 +2429,7 @@
props.setData(baos.toByteArray());
props.setPropertyCount(numProperties);
-
+
// Record the changes to the references ...
if (refs != null && refs.hasWritten()) {
for (Reference reference : refs.getWritten()) {
@@ -2402,7 +2520,7 @@
// See if the location is already in the cache ...
Location cached = cache.getLocationFor(workspaceId, path);
if (cached != null) {
- return new ActualLocation(cached, cached.getUuid().toString(), null);
+ return new ActualLocation(original, cached.getUuid().toString(), null);
}
}
@@ -2437,7 +2555,7 @@
}
}
Path fullPath = pathFactory.createAbsolutePath(segments);
- Location newLocation = Location.create(fullPath, uuidProperty);
+ Location newLocation = original.with(fullPath);
cache.addNewNode(workspaceId, newLocation);
return new ActualLocation(newLocation, nodeUuidString, originalEntity);
}
@@ -2460,10 +2578,17 @@
if (cachedParent != null) {
// We know the UUID of the parent, so we can find the child a little faster
...
ChildEntity child = findByPathSegment(workspaceId,
cachedParent.getUuid().toString(), path.getLastSegment());
+
+ // If there is no matching child, throw an exception
+ if (child == null) {
+ // Could not find the node given the supplied path, so find the lowest
path that does exist ...
+ throw new PathNotFoundException(original, cachedParent.getPath(),
JpaConnectorI18n.nodeDoesNotExist.text(path));
+ }
+
uuidString = child.getId().getChildUuidString();
Location newLocation = original.with(UUID.fromString(uuidString));
cache.addNewNode(workspaceId, newLocation);
- return new ActualLocation(newLocation, uuidString, child);
+ return new ActualLocation(original, uuidString, child);
}
// We couldn't find the parent, so we need to search by path ...
@@ -2489,6 +2614,18 @@
return new ActualLocation(newLocation, uuidString, child);
}
+ protected ChildEntity findNode( long workspaceId, String uuidString) {
+ Query query =
entities.createNamedQuery("ChildEntity.findByChildUuid");
+ query.setParameter("workspaceId", workspaceId);
+ query.setParameter("childUuidString", uuidString);
+ try {
+ // Find the parent of the UUID ...
+ return (ChildEntity)query.getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
/**
* Find the node with the supplied path segment that is a child of the supplied
parent.
*
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/model/basic/ChildEntity.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -310,4 +310,38 @@
}
}
+ @SuppressWarnings( "unchecked" )
+ public static int adjustSnsIndexesAndIndexes( EntityManager entities,
+ Long workspaceId,
+ String uuidParent,
+ int afterIndex,
+ int untilIndex,
+ long childNamespaceIndex,
+ String childName,
+ int modifier ) {
+ int snsCount = 0;
+
+ // Decrement the 'indexInParent' index values for all nodes above the
previously removed sibling ...
+ Query query =
entities.createNamedQuery("ChildEntity.findChildrenAfterIndexUnderParent");
+ query.setParameter("workspaceId", workspaceId);
+ query.setParameter("parentUuidString", uuidParent);
+ query.setParameter("afterIndex", afterIndex);
+
+ int index = afterIndex;
+ for (ChildEntity entity : (List<ChildEntity>)query.getResultList()) {
+ if (++index > untilIndex) {
+ break;
+ }
+
+ // Decrement the index in parent ...
+ entity.setIndexInParent(entity.getIndexInParent() + modifier);
+ if (entity.getChildName().equals(childName) &&
entity.getChildNamespace().getId() == childNamespaceIndex) {
+ // The name matches, so decrement the SNS index ...
+ entity.setSameNameSiblingIndex(entity.getSameNameSiblingIndex() +
modifier);
+ snsCount++;
+ }
+ }
+
+ return snsCount;
+ }
}
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/util/Serializer.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -217,7 +217,7 @@
final Name name = property.getName();
if (this.excludeUuidProperty && DnaLexicon.UUID.equals(name)) return
false;
// Write the name ...
- stream.writeObject(name.getString());
+ stream.writeObject(name.getString(Path.NO_OP_ENCODER));
// Write the number of values ...
stream.writeInt(property.size());
for (Object value : property) {
@@ -277,7 +277,7 @@
}
} else if (value instanceof Name) {
stream.writeChar('N');
- stream.writeObject(((Name)value).getString());
+ stream.writeObject(((Name)value).getString(Path.NO_OP_ENCODER));
} else if (value instanceof Path) {
stream.writeChar('P');
stream.writeObject(((Path)value).getString());
Modified:
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaConnectorWritingTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -57,6 +57,7 @@
source.setMaximumConnectionIdleTimeInSeconds(0);
source.setReferentialIntegrityEnforced(true);
source.setLargeValueSizeInBytes(150);
+ source.setCompressData(true);
return source;
}
Modified:
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java 2009-07-17
19:12:26 UTC (rev 1114)
+++
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java 2009-07-20
12:18:58 UTC (rev 1115)
@@ -58,7 +58,7 @@
this.source.setNumberOfConnectionsToAcquireAsNeeded(1);
this.source.setMaximumSizeOfStatementCache(100);
this.source.setMaximumConnectionIdleTimeInSeconds(0);
- this.source.setNameOfDefaultWorkspace("default");
+ this.source.setDefaultWorkspaceName("default");
this.source.setCreatingWorkspacesAllowed(true);
}