[dna-commits] DNA SVN: r1175 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/property/basic and 6 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Wed Aug 26 16:43:46 EDT 2009


Author: rhauch
Date: 2009-08-26 16:43:45 -0400 (Wed, 26 Aug 2009)
New Revision: 1175

Added:
   trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/SvnAndJcrIntegrationTest.java
   trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNIntegrationTest.java
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
   trunk/dna-integration-tests/pom.xml
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrConfigurationTest.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java
   trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorCreateWorspaceTest.java
Log:
DNA-505 Svn Repository Source with NPE and other issues while opening connection through Jcr
DNA-240 code test case for SVNRepositoryConnection used for connection

One of the NPE issues (DNA-505) was more easily fixed by returning an empty collection; the other was fixed as prescribed in the patch (though there was another situation that required a similar change).  A test case was added to the 'dna-connector-svn' project to test using the DNA SVN repository, and this made apparent several other issues.  First, the children for a directory were being computed incorrectly; all of the child directories were fine, but the locations of the nt:file nodes were being skipped and instead the path to the nt:file's jcr:content child node were being returned.  Second, much of the JCR implementation relies upon ReadNodeRequest instead of the ReadAllPropertiesRequest and ReadAllChildrenRequest.  Although the default implementation for ReadNodeRequest uses the other two and is technically correct, it can be quite inefficient, and this was definitely true for the SVN connector.  Therefore, the request processor code was refactored to have a single me!
 thod compute the children and/or the properties for a node.  This not only dramatically reduced the class size, but it dramatically reduced the amount of duplicated code, and it appears to have slightly improved performance (though I think the SVNKit is still the bottleneck).

Finally, a new integration test was added to the 'dna-integration-test' project that very minimally tests using JCR on top of the SVN connector.  This may need to be rounded out in the future, but ideally we wouldn't be hitting a remote SVN repository (simply because of the latency issue).

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/Path.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -398,6 +398,25 @@
     public Segment getLastSegment();
 
     /**
+     * Determine if the path's {@link #getLastSegment()} has the supplied name and no {@link Segment#getIndex() SNS index}.
+     * 
+     * @param nameOfLastSegment the name
+     * @return return true if the supplied name is the name in the path's last segment (and there is no SNS index), or false
+     *         otherwise
+     */
+    public boolean endsWith( Name nameOfLastSegment );
+
+    /**
+     * Determine if the path's {@link #getLastSegment()} has the supplied name and {@link Segment#getIndex() SNS index}.
+     * 
+     * @param nameOfLastSegment the name
+     * @param snsIndex the SNS index
+     * @return return true if the path's last segment has the supplied name and SNS, or false otherwise
+     */
+    public boolean endsWith( Name nameOfLastSegment,
+                             int snsIndex );
+
+    /**
      * Get the segment at the supplied index.
      * 
      * @param index the index

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/AbstractPath.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -35,6 +35,7 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.GraphI18n;
 import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Name;
 import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.jboss.dna.graph.property.Path;
 
@@ -187,6 +188,27 @@
     /**
      * {@inheritDoc}
      * 
+     * @see org.jboss.dna.graph.property.Path#endsWith(org.jboss.dna.graph.property.Name)
+     */
+    public boolean endsWith( Name nameOfLastSegment ) {
+        Segment segment = getLastSegment();
+        return segment != null && segment.getName().equals(nameOfLastSegment) && !segment.hasIndex();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.Path#endsWith(org.jboss.dna.graph.property.Name, int)
+     */
+    public boolean endsWith( Name nameOfLastSegment,
+                             int snsIndex ) {
+        Segment segment = getLastSegment();
+        return segment != null && segment.getName().equals(nameOfLastSegment) && segment.getIndex() == snsIndex;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
      * @see org.jboss.dna.graph.property.Path#getParent()
      */
     public Path getParent() {

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/property/basic/RootPath.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -32,6 +32,7 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.GraphI18n;
 import org.jboss.dna.graph.property.InvalidPathException;
+import org.jboss.dna.graph.property.Name;
 import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.jboss.dna.graph.property.Path;
 
@@ -114,6 +115,27 @@
     /**
      * {@inheritDoc}
      * 
+     * @see org.jboss.dna.graph.property.basic.AbstractPath#endsWith(org.jboss.dna.graph.property.Name)
+     */
+    @Override
+    public boolean endsWith( Name nameOfLastSegment ) {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.property.basic.AbstractPath#endsWith(org.jboss.dna.graph.property.Name, int)
+     */
+    @Override
+    public boolean endsWith( Name nameOfLastSegment,
+                             int snsIndex ) {
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
      * @see org.jboss.dna.graph.property.Path#getNormalizedPath()
      */
     @Override

Modified: trunk/dna-integration-tests/pom.xml
===================================================================
--- trunk/dna-integration-tests/pom.xml	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-integration-tests/pom.xml	2009-08-26 20:43:45 UTC (rev 1175)
@@ -81,6 +81,12 @@
 			<version>${pom.version}</version>
 			<scope>test</scope>
 		</dependency>
+        <dependency>
+            <groupId>org.jboss.dna</groupId>
+            <artifactId>dna-connector-svn</artifactId>
+            <version>${pom.version}</version>
+            <scope>test</scope>
+        </dependency>
 
 		<!-- 
           JPA Connector Dependencies

Added: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/SvnAndJcrIntegrationTest.java
===================================================================
--- trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/SvnAndJcrIntegrationTest.java	                        (rev 0)
+++ trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/SvnAndJcrIntegrationTest.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -0,0 +1,122 @@
+/*
+ * 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 static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import javax.jcr.NodeIterator;
+import javax.jcr.Session;
+import org.jboss.dna.connector.svn.SVNRepositorySource;
+import org.jboss.dna.graph.SecurityContext;
+import org.jboss.dna.jcr.JcrConfiguration;
+import org.jboss.dna.jcr.JcrEngine;
+import org.jboss.dna.jcr.SecurityContextCredentials;
+import org.jboss.dna.jcr.JcrRepository.Option;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * 
+ */
+public class SvnAndJcrIntegrationTest {
+    private JcrEngine engine;
+    private Session session;
+
+    @Before
+    public void beforeEach() throws Exception {
+        final String repositoryUrl = "http://anonsvn.jboss.org/repos/dna/";
+        final String[] predefinedWorkspaceNames = {repositoryUrl + "trunk", repositoryUrl + "tags", repositoryUrl + "branches"};
+        final String svnRepositorySource = "svnRepositorySource";
+        final String repositoryName = "svnRepository";
+        final JcrConfiguration configuration = new JcrConfiguration();
+        configuration.repositorySource(svnRepositorySource)
+                     .usingClass(SVNRepositorySource.class)
+                     .setProperty("password", "")
+                     .setProperty("username", "anonymous")
+                     .setProperty("repositoryRootURL", repositoryUrl)
+                     .setProperty("predefinedWorkspaceNames", predefinedWorkspaceNames)
+                     .setProperty("directoryForDefaultWorkspace", predefinedWorkspaceNames[0])
+                     .setProperty("creatingWorkspacesAllowed", false);
+
+        configuration.repository(repositoryName).setSource(svnRepositorySource).setOption(Option.READ_DEPTH, "1");
+        configuration.save();
+        this.engine = configuration.build();
+        this.engine.start();
+
+        this.session = this.engine.getRepository(repositoryName)
+                                  .login(new SecurityContextCredentials(new MyCustomSecurityContext()));
+
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (this.session != null) {
+            this.session.logout();
+        }
+        if (this.engine != null) {
+            this.engine.shutdown();
+        }
+    }
+
+    @Test
+    public void shouldIterateOverChildrenOfRoot() throws Exception {
+        NodeIterator nodeIterator = this.session.getRootNode().getNodes();
+
+        while (nodeIterator.hasNext()) {
+            System.out.println(nodeIterator.nextNode().getPath());
+        }
+        assertThat(this.session.getRootNode().getNode("dna-graph"), is(notNullValue()));
+    }
+
+    protected class MyCustomSecurityContext implements SecurityContext {
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.SecurityContext#getUserName()
+         */
+        public String getUserName() {
+            return "Fred";
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.SecurityContext#hasRole(java.lang.String)
+         */
+        public boolean hasRole( String roleName ) {
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.graph.SecurityContext#logout()
+         */
+        public void logout() {
+            // do something
+        }
+    }
+}


Property changes on: trunk/dna-integration-tests/src/test/java/org/jboss/dna/test/integration/SvnAndJcrIntegrationTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -132,9 +132,14 @@
          * Also, any use of the '@' character in source and workspace names must be escaped with a preceding backslash.
          * </p>
          */
-        SYSTEM_SOURCE_NAME;
+        SYSTEM_SOURCE_NAME,
 
         /**
+         * The depth of the subgraphs that should be loaded the connectors. The default value is 1.
+         */
+        READ_DEPTH;
+
+        /**
          * Determine the option given the option name. This does more than {@link Option#valueOf(String)}, since this method first
          * tries to match the supplied string to the option's {@link Option#name() name}, then the uppercase version of the
          * supplied string to the option's name, and finally if the supplied string is a camel-case version of the name (e.g.,
@@ -176,6 +181,11 @@
          * The default value for the {@link Option#JAAS_LOGIN_CONFIG_NAME} option is {@value} .
          */
         public static final String JAAS_LOGIN_CONFIG_NAME = "dna-jcr";
+
+        /**
+         * The default value for the {@link Option#READ_DEPTH} option is {@value} .
+         */
+        public static final String READ_DEPTH = "1";
     }
 
     /**
@@ -188,6 +198,7 @@
         EnumMap<Option, String> defaults = new EnumMap<Option, String>(Option.class);
         defaults.put(Option.PROJECT_NODE_TYPES, DefaultOption.PROJECT_NODE_TYPES);
         defaults.put(Option.JAAS_LOGIN_CONFIG_NAME, DefaultOption.JAAS_LOGIN_CONFIG_NAME);
+        defaults.put(Option.READ_DEPTH, DefaultOption.READ_DEPTH);
         DEFAULT_OPTIONS = Collections.<Option, String>unmodifiableMap(defaults);
     }
 

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-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SessionCache.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -76,6 +76,7 @@
 import org.jboss.dna.graph.session.GraphSession.NodeId;
 import org.jboss.dna.graph.session.GraphSession.PropertyInfo;
 import org.jboss.dna.graph.session.GraphSession.Status;
+import org.jboss.dna.jcr.JcrRepository.Option;
 
 /**
  * The class that manages the session's information that has been locally-cached after reading from the underlying {@link Graph
@@ -172,6 +173,12 @@
         // Create the graph session, customized for JCR ...
         this.graphSession = new GraphSession<JcrNodePayload, JcrPropertyPayload>(this.store, this.workspaceName,
                                                                                  new JcrNodeOperations(), new JcrAuthorizer());
+        // Set the read-depth if we can...
+        try {
+            int depth = Integer.parseInt(session.repository().getOptions().get(Option.READ_DEPTH));
+            if (depth > 0) this.graphSession.setDepthForLoadingNodes(depth);
+        } catch (RuntimeException e) {
+        }
     }
 
     final GraphSession<JcrNodePayload, JcrPropertyPayload> graphSession() {
@@ -937,8 +944,7 @@
                                                                 true,
                                                                 skipProtected);
                 if (definition == null) {
-                    throw new ConstraintViolationException(
-                                                           JcrI18n.noDefinition.text("property",
+                    throw new ConstraintViolationException(JcrI18n.noDefinition.text("property",
                                                                                      readable(name),
                                                                                      readable(node.getPath()),
                                                                                      readable(payload.getPrimaryTypeName()),
@@ -1114,8 +1120,7 @@
                                                                 newValues,
                                                                 skipProtected);
                 if (definition == null) {
-                    throw new ConstraintViolationException(
-                                                           JcrI18n.noDefinition.text("property",
+                    throw new ConstraintViolationException(JcrI18n.noDefinition.text("property",
                                                                                      readable(name),
                                                                                      readable(node.getPath()),
                                                                                      readable(payload.getPrimaryTypeName()),
@@ -1249,8 +1254,8 @@
                     // The node definition changed, so try to set the property ...
                     NodeEditor newChildEditor = getEditorFor(existingChild);
                     try {
-                        JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING,
-                                                      defn.getId().getString());
+                        JcrValue value = new JcrValue(factories(), SessionCache.this, PropertyType.STRING, defn.getId()
+                                                                                                               .getString());
                         newChildEditor.setProperty(DnaIntLexicon.NODE_DEFINITON, value);
                     } catch (ConstraintViolationException e) {
                         // We can't set this property on the node (according to the node definition).

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrConfigurationTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrConfigurationTest.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrConfigurationTest.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -48,6 +48,7 @@
 import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
 import org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector;
 import org.jboss.dna.graph.property.Path;
+import org.jboss.dna.jcr.JcrRepository.DefaultOption;
 import org.jboss.dna.jcr.JcrRepository.Option;
 import org.jboss.dna.repository.DnaConfiguration;
 import org.jboss.dna.repository.DnaLexicon;
@@ -246,7 +247,8 @@
 
         Map<Option, String> options = new HashMap<Option, String>();
         options.put(Option.JAAS_LOGIN_CONFIG_NAME, "test");
-        options.put(Option.PROJECT_NODE_TYPES, "false");
+        options.put(Option.PROJECT_NODE_TYPES, DefaultOption.PROJECT_NODE_TYPES);
+        options.put(Option.READ_DEPTH, DefaultOption.READ_DEPTH);
         assertThat(repository.getOptions(), is(options));
     }
 

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -29,6 +29,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Set;
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.Logger;
@@ -63,6 +65,7 @@
 import org.jboss.dna.graph.request.MoveBranchRequest;
 import org.jboss.dna.graph.request.ReadAllChildrenRequest;
 import org.jboss.dna.graph.request.ReadAllPropertiesRequest;
+import org.jboss.dna.graph.request.ReadNodeRequest;
 import org.jboss.dna.graph.request.RenameNodeRequest;
 import org.jboss.dna.graph.request.Request;
 import org.jboss.dna.graph.request.UpdatePropertiesRequest;
@@ -128,188 +131,176 @@
         this.accessData = accessData;
     }
 
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
-     */
-    @Override
-    public void process( ReadAllChildrenRequest request ) {
-        logger.trace(request.toString());
+    protected boolean readNode( String workspaceName,
+                                Location myLocation,
+                                List<Property> properties,
+                                List<Location> children,
+                                Request request ) {
 
         // Get the SVNRepository object that represents the workspace ...
-        SVNRepository workspaceRoot = getWorkspaceDirectory(request.inWorkspace());
+        SVNRepository workspaceRoot = getWorkspaceDirectory(workspaceName);
         if (workspaceRoot == null) {
-            request.setError(new InvalidWorkspaceException(
-                                                           SVNRepositoryConnectorI18n.workspaceDoesNotExist.text(request.inWorkspace())));
-            return;
+            request.setError(new InvalidWorkspaceException(SVNRepositoryConnectorI18n.workspaceDoesNotExist.text(workspaceName)));
+            return false;
         }
-        Location myLocation = request.of();
         Path requestedPath = getPathFor(myLocation, request);
-        // svn connector does not support same name sibling
-        checkThePath(requestedPath, request);
-        // requested path is the root
+        checkThePath(requestedPath, request); // same-name-sibling indexes are not supported
+
         if (requestedPath.isRoot()) {
             // workspace root must be a directory
-            final Collection<SVNDirEntry> entries = SVNRepositoryUtil.getDir(workspaceRoot, "");
-            for (SVNDirEntry entry : entries) {
-                // Decide how to represent the children ...
-                if (entry.getKind() == SVNNodeKind.DIR) {
-                    // Create a Location for each file and directory contained by the parent directory ...
+            if (children != null) {
+                final Collection<SVNDirEntry> entries = SVNRepositoryUtil.getDir(workspaceRoot, "");
+                for (SVNDirEntry entry : entries) {
+                    // All of the children of a directory will be another directory or a file, but never a "jcr:content" node ...
                     String localName = entry.getName();
                     Name childName = nameFactory().create(defaultNamespaceUri, localName);
                     Path childPath = pathFactory().create(requestedPath, childName);
-                    request.addChild(Location.create(childPath));
-                } else if (entry.getKind() == SVNNodeKind.FILE) {
-                    // The parent is a file, and the path may refer to the node that is either the "nt:file" parent
-                    // node, or the child "jcr:content" node...
-                    String localName = entry.getName();
-                    Path contentPath = pathFactory().create(BACK_SLASH + localName);
-                    if (!contentPath.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
-                        Location location = Location.create(pathFactory().create(contentPath, JcrLexicon.CONTENT));
-                        request.addChild(location);
-                    }
+                    children.add(Location.create(childPath));
                 }
             }
+            // There are no properties on the root ...
         } else {
             try {
-                SVNNodeKind kind = getNodeKind(workspaceRoot,
-                                               requestedPath,
-                                               accessData.getRepositoryRootUrl(),
-                                               request.inWorkspace());
+                // Generate the properties for this File object ...
+                PropertyFactory factory = getExecutionContext().getPropertyFactory();
+                DateTimeFactory dateFactory = getExecutionContext().getValueFactories().getDateFactory();
+
+                // Figure out the kind of node this represents ...
+                SVNNodeKind kind = getNodeKind(workspaceRoot, requestedPath, accessData.getRepositoryRootUrl(), workspaceName);
                 if (kind == SVNNodeKind.DIR) {
                     String directoryPath = getPathAsString(requestedPath);
-                    // Decide how to represent the children ...
-                    if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                    if (!accessData.getRepositoryRootUrl().equals(workspaceName)) {
                         directoryPath = directoryPath.substring(1);
                     }
-                    Collection<SVNDirEntry> dirEntries = SVNRepositoryUtil.getDir(workspaceRoot, directoryPath);
-                    for (SVNDirEntry entry : dirEntries) {
+                    if (children != null) {
                         // Decide how to represent the children ...
-                        if (entry.getKind() == SVNNodeKind.DIR) {
-                            // Create a Location for each file and directory contained by the parent directory ...
+                        Collection<SVNDirEntry> dirEntries = SVNRepositoryUtil.getDir(workspaceRoot, directoryPath);
+                        for (SVNDirEntry entry : dirEntries) {
+                            // All of the children of a directory will be another directory or a file,
+                            // but never a "jcr:content" node ...
                             String localName = entry.getName();
                             Name childName = nameFactory().create(defaultNamespaceUri, localName);
                             Path childPath = pathFactory().create(requestedPath, childName);
-                            request.addChild(Location.create(childPath));
-                        } else if (entry.getKind() == SVNNodeKind.FILE) {
-                            // The parent is a file, and the path may refer to the node that is either the "nt:file" parent
-                            // node, or the child "jcr:content" node...
-                            String localName = entry.getName();
-                            Path contentPath = pathFactory().create(getPathAsString(requestedPath) + BACK_SLASH + localName);
-                            Location content = Location.create(pathFactory().create(contentPath, JcrLexicon.CONTENT));
-                            request.addChild(content);
+                            children.add(Location.create(childPath));
                         }
                     }
+                    if (properties != null) {
+                        // Load the properties for this directory ......
+                        properties.add(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FOLDER));
+                        SVNDirEntry entry = getEntryInfo(workspaceRoot, directoryPath);
+                        if (entry != null) {
+                            properties.add(factory.create(JcrLexicon.LAST_MODIFIED, dateFactory.create(entry.getDate())));
+                        }
+                    }
                 } else {
-                    if (!requestedPath.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
-                        // Use leading '/' on the requested path
-                        // repository root URL is exactly the same as the workspace
-                        // Get the parent path
+                    // It's not a directory, so must be a file; the only child of an nt:file is the "jcr:content" node
+                    // ...
+                    if (requestedPath.endsWith(JcrLexicon.CONTENT)) {
+                        // There are never any children of these nodes, just properties ...
+                        if (properties != null) {
+                            String contentPath = getPathAsString(requestedPath.getParent());
+                            if (!accessData.getRepositoryRootUrl().equals(workspaceName)) {
+                                contentPath = contentPath.substring(1);
+                            }
+                            SVNDirEntry entry = getEntryInfo(workspaceRoot, contentPath);
+                            if (entry != null) {
+                                // The request is to get properties of the "jcr:content" child node ...
+                                properties.add(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.RESOURCE));
+                                properties.add(factory.create(JcrLexicon.LAST_MODIFIED, dateFactory.create(entry.getDate())));
+                            }
+
+                            ByteArrayOutputStream os = new ByteArrayOutputStream();
+                            SVNProperties fileProperties = new SVNProperties();
+                            getData(contentPath, fileProperties, os);
+                            String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE);
+                            if (mimeType == null) mimeType = DEFAULT_MIME_TYPE;
+                            properties.add(factory.create(JcrLexicon.MIMETYPE, mimeType));
+
+                            if (os.toByteArray().length > 0) {
+                                // Now put the file's content into the "jcr:data" property ...
+                                BinaryFactory binaryFactory = getExecutionContext().getValueFactories().getBinaryFactory();
+                                properties.add(factory.create(JcrLexicon.DATA, binaryFactory.create(os.toByteArray())));
+                            }
+                        }
+                    } else {
+                        // Determine the corresponding file path for this object ...
                         String filePath = getPathAsString(requestedPath);
-                        if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                        if (!accessData.getRepositoryRootUrl().equals(workspaceName)) {
                             filePath = filePath.substring(1);
                         }
-                        Path contentPath = pathFactory().create(requestedPath, JcrLexicon.CONTENT);
-                        Location content = Location.create(contentPath);
-                        request.addChild(content);
+                        if (children != null) {
+                            // Not a "jcr:content" child node but rather an nt:file node, so add the child ...
+                            Path contentPath = pathFactory().create(requestedPath, JcrLexicon.CONTENT);
+                            children.add(Location.create(contentPath));
+                        }
+                        if (properties != null) {
+                            // Now add the properties to "nt:file" ...
+                            properties.add(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FILE));
+                            ByteArrayOutputStream os = new ByteArrayOutputStream();
+                            SVNProperties fileProperties = new SVNProperties();
+                            getData(filePath, fileProperties, os);
+                            String created = fileProperties.getStringValue(SVNProperty.COMMITTED_DATE);
+                            if (created != null) {
+                                properties.add(factory.create(JcrLexicon.CREATED, dateFactory.create(created)));
+                            }
+                        }
                     }
                 }
             } catch (SVNException e) {
                 request.setError(e);
             }
         }
-        request.setActualLocationOfNode(myLocation);
-        setCacheableInfo(request);
+        return true;
     }
 
     /**
      * {@inheritDoc}
      * 
-     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadNodeRequest)
      */
     @Override
-    public void process( ReadAllPropertiesRequest request ) {
+    public void process( ReadNodeRequest request ) {
         logger.trace(request.toString());
-
-        // Get the SVNRepository object that represents the workspace ...
-        SVNRepository workspaceRoot = getWorkspaceDirectory(request.inWorkspace());
-        if (workspaceRoot == null) {
-            request.setError(new InvalidWorkspaceException(
-                                                           SVNRepositoryConnectorI18n.workspaceDoesNotExist.text(request.inWorkspace())));
-            return;
+        List<Location> children = new LinkedList<Location>();
+        List<Property> properties = new LinkedList<Property>();
+        if (readNode(request.inWorkspace(), request.at(), properties, children, request)) {
+            request.addChildren(children);
+            request.addProperties(properties);
+            request.setActualLocationOfNode(request.at());
+            setCacheableInfo(request);
         }
+    }
 
-        // Find the existing file for the parent ...
-        Location myLocation = request.at();
-        Path requestedPath = getPathFor(myLocation, request);
-        if (requestedPath.isRoot()) {
-            // There are no properties on the root ...
-            request.setActualLocationOfNode(myLocation);
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllChildrenRequest)
+     */
+    @Override
+    public void process( ReadAllChildrenRequest request ) {
+        logger.trace(request.toString());
+        List<Location> children = new LinkedList<Location>();
+        if (readNode(request.inWorkspace(), request.of(), null, children, request)) {
+            request.addChildren(children);
+            request.setActualLocationOfNode(request.of());
             setCacheableInfo(request);
-            return;
         }
 
-        try {
+    }
 
-            SVNNodeKind kind = getNodeKind(workspaceRoot, requestedPath, accessData.getRepositoryRootUrl(), request.inWorkspace());
-            // Generate the properties for this File object ...
-            PropertyFactory factory = getExecutionContext().getPropertyFactory();
-            DateTimeFactory dateFactory = getExecutionContext().getValueFactories().getDateFactory();
-            // Note that we don't have 'created' timestamps, just last modified, so we'll have to use them
-            if (kind == SVNNodeKind.DIR) {
-                String directoryPath = getPathAsString(requestedPath);
-                if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
-                    directoryPath = directoryPath.substring(1);
-                }
-                request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FOLDER));
-                SVNDirEntry entry = getEntryInfo(workspaceRoot, directoryPath);
-                request.addProperty(factory.create(JcrLexicon.LAST_MODIFIED, dateFactory.create(entry.getDate())));
-            } else {
-                if (requestedPath.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
-                    String contentPath = getPathAsString(requestedPath.getParent());
-                    if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
-                        contentPath = contentPath.substring(1);
-                    }
-                    SVNDirEntry entry = getEntryInfo(workspaceRoot, contentPath);
-                    // The request is to get properties of the "jcr:content" child node ...
-                    request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.RESOURCE));
-                    request.addProperty(factory.create(JcrLexicon.LAST_MODIFIED, dateFactory.create(entry.getDate())));
-
-                    ByteArrayOutputStream os = new ByteArrayOutputStream();
-                    SVNProperties fileProperties = new SVNProperties();
-                    getData(contentPath, fileProperties, os);
-                    String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE);
-                    if (mimeType == null) mimeType = DEFAULT_MIME_TYPE;
-                    request.addProperty(factory.create(JcrLexicon.MIMETYPE, mimeType));
-
-                    if (os.toByteArray().length > 0) {
-                        // Now put the file's content into the "jcr:data" property ...
-                        BinaryFactory binaryFactory = getExecutionContext().getValueFactories().getBinaryFactory();
-                        request.addProperty(factory.create(JcrLexicon.DATA, binaryFactory.create(os.toByteArray())));
-                    }
-
-                } else {
-                    String filePath = getPathAsString(requestedPath);
-                    if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
-                        filePath = filePath.substring(1);
-                    }
-                    // The request is to get properties for the node representing the file
-                    request.addProperty(factory.create(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FILE));
-                    ByteArrayOutputStream os = new ByteArrayOutputStream();
-                    SVNProperties fileProperties = new SVNProperties();
-                    getData(filePath, fileProperties, os);
-                    String created = fileProperties.getStringValue(SVNProperty.COMMITTED_DATE);
-                    if (created != null) {
-                        request.addProperty(factory.create(JcrLexicon.CREATED, dateFactory.create(created)));
-                    }
-                }
-            }
-            request.setActualLocationOfNode(myLocation);
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.ReadAllPropertiesRequest)
+     */
+    @Override
+    public void process( ReadAllPropertiesRequest request ) {
+        logger.trace(request.toString());
+        List<Property> properties = new LinkedList<Property>();
+        if (readNode(request.inWorkspace(), request.at(), properties, null, request)) {
+            request.addProperties(properties);
+            request.setActualLocationOfNode(request.at());
             setCacheableInfo(request);
-
-        } catch (SVNException e) {
-            request.setError(e);
         }
     }
 
@@ -626,7 +617,7 @@
         String myPath;
         if (getPathAsString(requestedPath).trim().equals("/")) {
             myPath = getPathAsString(requestedPath);
-        } else if (requestedPath.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
+        } else if (requestedPath.endsWith(JcrLexicon.CONTENT)) {
             myPath = getPathAsString(requestedPath.getParent());
         } else {
             // directory and file
@@ -663,7 +654,7 @@
      * 
      * @param repos
      * @param path - the path
-     * @return - the {@link SVNDirEntry}.
+     * @return - the {@link SVNDirEntry}, or null if there is no such entry
      */
     protected SVNDirEntry getEntryInfo( SVNRepository repos,
                                         String path ) {
@@ -1025,7 +1016,7 @@
         assert repositoryRootUrl != null;
         assert inWorkspace != null;
         // See if the path is a "jcr:content" node ...
-        if (path.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
+        if (path.endsWith(JcrLexicon.CONTENT)) {
             // We only want to use the parent path to find the actual file ...
             path = path.getParent();
         }

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -1,6 +1,7 @@
 package org.jboss.dna.connector.svn;
 
 import java.util.Collection;
+import java.util.Collections;
 import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.request.InvalidWorkspaceException;
 import org.tmatesoft.svn.core.SVNDirEntry;
@@ -159,16 +160,15 @@
     /**
      * @param repos
      * @param path
-     * @return a collect of entry from directory path.
+     * @return a collect of entry from directory path; never null
      */
     @SuppressWarnings( "unchecked" )
     public static Collection<SVNDirEntry> getDir( SVNRepository repos,
                                                   String path ) {
-        Collection<SVNDirEntry> entries = null;
         try {
             return repos.getDir(path, -1, null, (Collection<SVNDirEntry>)null);
         } catch (SVNException e) {
-            return entries;
+            return Collections.emptyList();
         }
     }
 

Added: trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNIntegrationTest.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNIntegrationTest.java	                        (rev 0)
+++ trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNIntegrationTest.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -0,0 +1,79 @@
+/*
+ * 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.connector.svn;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.util.Map;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.Node;
+import org.jboss.dna.graph.property.Name;
+import org.jboss.dna.graph.property.Property;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SVNIntegrationTest {
+
+    private ExecutionContext context;
+    private SVNRepositorySource source;
+    private String repositoryUrl;
+    private String[] predefinedWorkspaceNames;
+
+    @Before
+    public void beforeEach() {
+        repositoryUrl = "http://anonsvn.jboss.org/repos/dna/";
+        predefinedWorkspaceNames = new String[] {repositoryUrl + "trunk", repositoryUrl + "tags", repositoryUrl + "branches"};
+        context = new ExecutionContext();
+        source = new SVNRepositorySource();
+        source.setName("svn repository source");
+        source.setRepositoryRootURL(repositoryUrl);
+        source.setUsername("anonymous");
+        source.setPassword("");
+        source.setCreatingWorkspacesAllowed(true);
+        source.setPredefinedWorkspaceNames(predefinedWorkspaceNames);
+        source.setDirectoryForDefaultWorkspace(predefinedWorkspaceNames[0]);
+        source.setCreatingWorkspacesAllowed(false);
+    }
+
+    @Test
+    public void shouldConnectAndReadRootNode() {
+        Graph graph = Graph.create(source, context);
+        Map<Name, Property> properties = graph.getPropertiesByName().on("/");
+        assertThat(properties, is(notNullValue()));
+
+        Node root = graph.getNodeAt("/");
+        assertThat(root, is(notNullValue()));
+        assertThat(root.getLocation(), is(notNullValue()));
+        assertThat(root.getChildren().isEmpty(), is(false));
+        for (Location childLocation : root.getChildren()) {
+            assertThat(childLocation.getPath().getParent().isRoot(), is(true));
+            // Node child = graph.getNodeAt(childLocation);
+            // assertThat(child.getLocation(), is(childLocation));
+            // assertThat(child.getLocation().getPath().getParent().isRoot(), is(true));
+        }
+    }
+}


Property changes on: trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNIntegrationTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorCreateWorspaceTest.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorCreateWorspaceTest.java	2009-08-26 18:10:37 UTC (rev 1174)
+++ trunk/extensions/dna-connector-svn/src/test/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorCreateWorspaceTest.java	2009-08-26 20:43:45 UTC (rev 1175)
@@ -85,4 +85,10 @@
         assertThat(workspaceNames.isEmpty(), is(true));
     }
 
+    @Test
+    @Override
+    public void shouldReadTheChildrenOfTheRootNodeInEachWorkspace() {
+        super.shouldReadTheChildrenOfTheRootNodeInEachWorkspace();
+    }
+
 }



More information about the dna-commits mailing list