[dna-commits] DNA SVN: r1490 - trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Tue Dec 29 17:46:45 EST 2009


Author: spagop
Date: 2009-12-29 17:46:45 -0500 (Tue, 29 Dec 2009)
New Revision: 1490

Modified:
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorI18n.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/SVNRepositorySource.java
   trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java
Log:
some write svn access (add file/dir, update file)

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorI18n.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorI18n.java	2009-12-29 22:46:08 UTC (rev 1489)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryConnectorI18n.java	2009-12-29 22:46:45 UTC (rev 1490)
@@ -53,6 +53,16 @@
     public static I18n sameNameSiblingsAreNotAllowed;
     public static I18n onlyTheDefaultNamespaceIsAllowed;
     public static I18n unableToCreateWorkspaces;
+    public static I18n pathForRequestIsNotCorrect;
+    public static I18n pathForRequestMustStartWithAForwardSlash;
+    public static I18n nodeAlreadyExist;
+    public static I18n unsupportedPrimaryType;
+    public static I18n invalidPropertyNames;
+    public static I18n invalidNameForResource;
+    public static I18n invalidPathForResource;
+    public static I18n missingRequiredProperty;
+    public static I18n couldNotCreateFile;
+    public static I18n couldNotReadData;
 
     static {
         try {
@@ -73,4 +83,6 @@
     public static Set<String> getLocalizationProblems( Locale locale ) {
         return I18n.getLocalizationProblems(SVNRepositoryConnectorI18n.class, locale);
     }
+
+  
 }

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-12-29 22:46:08 UTC (rev 1489)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryRequestProcessor.java	2009-12-29 22:46:45 UTC (rev 1490)
@@ -23,30 +23,38 @@
  */
 package org.jboss.dna.connector.svn;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import org.jboss.dna.common.i18n.I18n;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.connector.scm.ScmAction;
 import org.jboss.dna.connector.scm.ScmActionFactory;
+import org.jboss.dna.connector.svn.mgnt.AddDirectory;
+import org.jboss.dna.connector.svn.mgnt.AddFile;
+import org.jboss.dna.connector.svn.mgnt.MergeFile;
+import org.jboss.dna.graph.DnaIntLexicon;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.JcrNtLexicon;
 import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.NodeConflictBehavior;
 import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.property.Binary;
 import org.jboss.dna.graph.property.BinaryFactory;
 import org.jboss.dna.graph.property.DateTimeFactory;
 import org.jboss.dna.graph.property.Name;
 import org.jboss.dna.graph.property.NameFactory;
+import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.jboss.dna.graph.property.Path;
 import org.jboss.dna.graph.property.PathFactory;
 import org.jboss.dna.graph.property.PathNotFoundException;
@@ -79,9 +87,7 @@
 import org.tmatesoft.svn.core.SVNNodeKind;
 import org.tmatesoft.svn.core.SVNProperties;
 import org.tmatesoft.svn.core.SVNProperty;
-import org.tmatesoft.svn.core.io.ISVNEditor;
 import org.tmatesoft.svn.core.io.SVNRepository;
-import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
 
 /**
  * The {@link RequestProcessor} implementation for the file subversion repository connector. This is the class that does the bulk
@@ -93,6 +99,31 @@
 
     private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
 
+    /**
+     * Only certain properties are tolerated when writing content (dna:resource or jcr:resource) nodes. These properties are
+     * implicitly stored (primary type, data) or silently ignored (encoded, mimetype, last modified). The silently ignored
+     * properties must be accepted to stay compatible with the JCR specification.
+     */
+    private final Set<Name> ALLOWABLE_PROPERTIES_FOR_CONTENT = Collections.unmodifiableSet(new HashSet<Name>(
+                                                                                                             Arrays.asList(new Name[] {
+                                                                                                                 JcrLexicon.PRIMARY_TYPE,
+                                                                                                                 JcrLexicon.DATA,
+                                                                                                                 JcrLexicon.ENCODED,
+                                                                                                                 JcrLexicon.MIMETYPE,
+                                                                                                                 JcrLexicon.LAST_MODIFIED,
+                                                                                                                 JcrLexicon.UUID,
+                                                                                                                 DnaIntLexicon.NODE_DEFINITON})));
+    /**
+     * Only certain properties are tolerated when writing files (nt:file) or folders (nt:folder) nodes. These properties are
+     * implicitly stored in the file or folder (primary type, created).
+     */
+    private final Set<Name> ALLOWABLE_PROPERTIES_FOR_FILE_OR_FOLDER = Collections.unmodifiableSet(new HashSet<Name>(
+                                                                                                                    Arrays.asList(new Name[] {
+                                                                                                                        JcrLexicon.PRIMARY_TYPE,
+                                                                                                                        JcrLexicon.CREATED,
+                                                                                                                        JcrLexicon.UUID,
+                                                                                                                        DnaIntLexicon.NODE_DEFINITON})));
+
     private final String defaultNamespaceUri;
     private final boolean updatesAllowed;
     private SVNRepository defaultWorkspace;
@@ -321,10 +352,291 @@
      */
     @Override
     public void process( CreateNodeRequest request ) {
-        updatesAllowed(request);
+        logger.trace(request.toString());
+        if (!updatesAllowed(request)) return;
+
+        // continue
+        Path parentPath = getPathFor(request.under(), request);
+        if (parentPath == null) return;
+
+        // svn connector does not support same name sibling
+        sameNameSiblingIsNotSupported(parentPath, request);
+
+        SVNRepository workspaceRoot = getWorkspaceDirectory(request.inWorkspace());
+        assert workspaceRoot != null;
+
+        SVNNodeKind parent = getSVNNodeKindFor(workspaceRoot, parentPath, request.under(), request.inWorkspace(), request);
+        if (parent == null) {
+            return;
+        }
+
+        NamespaceRegistry registry = getExecutionContext().getNamespaceRegistry();
+        // New name to commit into the svn repos workspace
+        String newName = request.named().getString(registry);
+
+        // Collect all the properties of the node in a hash map
+        Map<Name, Property> properties = new HashMap<Name, Property>(request.properties().size());
+        for (Property property : request.properties()) {
+            properties.put(property.getName(), property);
+        }
+
+        Property primaryTypeProp = properties.get(JcrLexicon.PRIMARY_TYPE);
+        Name primaryType = primaryTypeProp == null ? null : nameFactory().create(primaryTypeProp.getFirstValue());
+
+        Path newPath = pathFactory().create(parentPath, request.named());
+        Location actualLocation = Location.create(newPath);
+
+        String newChildPath = null;
+
+        // File
+        if (JcrNtLexicon.FILE.equals(primaryType)) {
+            ensureValidProperties(request.properties(), ALLOWABLE_PROPERTIES_FOR_FILE_OR_FOLDER);
+            // Parent node already exist
+            boolean skipWrite = false;
+
+            if (request.under().getPath().isRoot()) {
+
+                if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                    newChildPath = newName;
+                } else {
+                    newChildPath = "/" + newName;
+                }
+            } else {
+
+                newChildPath = getPathAsString(request.under().getPath()) + "/" + newName;
+
+                if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                    newChildPath = newChildPath.substring(1);
+                }
+            }
+
+            // check if the new name already exist
+            if (SVNRepositoryUtil.exists(workspaceRoot, newChildPath)) {
+                if (request.conflictBehavior().equals(NodeConflictBehavior.APPEND)) {
+                    I18n msg = SVNRepositoryConnectorI18n.sameNameSiblingsAreNotAllowed;
+                    throw new InvalidRequestException(msg.text(this.getSourceName(), newName));
+                } else if (request.conflictBehavior().equals(NodeConflictBehavior.DO_NOT_REPLACE)) {
+                    skipWrite = true;
+                }
+            }
+            // Don't try to write if the node conflict behavior is DO_NOT_REPLACE
+            if (!skipWrite) {
+                // create a new, empty file
+                if (newChildPath != null) {
+                    try {
+                        String rootPath = null;
+                        if (request.under().getPath().isRoot()) {
+                            rootPath = "";
+                        } else {
+                            rootPath = getPathAsString(request.under().getPath());
+                        }
+                        newFile(rootPath, newName, "".getBytes(), null, request.inWorkspace(), this.defaultWorkspace);
+                    } catch (SVNException e) {
+                        I18n msg = SVNRepositoryConnectorI18n.couldNotCreateFile;
+                        request.setError(new RepositorySourceException(getSourceName(),
+                                                                       msg.text(getPathAsString(request.under().getPath()),
+                                                                                request.inWorkspace(),
+                                                                                getSourceName(),
+                                                                                e.getMessage()), e));
+                        return;
+                    }
+                }
+            }
+        } else if (JcrNtLexicon.RESOURCE.equals(primaryType) || DnaLexicon.RESOURCE.equals(primaryType)) { // Resource
+            ensureValidProperties(request.properties(), ALLOWABLE_PROPERTIES_FOR_CONTENT);
+            if (request.under().getPath().isRoot()) {
+                newChildPath = getPathAsString(parentPath);
+                if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                    newChildPath = getPathAsString(parentPath).substring(1);
+                }
+            } else {
+                newChildPath = getPathAsString(parentPath);
+                if (!accessData.getRepositoryRootUrl().equals(request.inWorkspace())) {
+                    newChildPath = newChildPath.substring(1);
+                }
+            }
+
+            if (!JcrLexicon.CONTENT.equals(request.named())) {
+                I18n msg = SVNRepositoryConnectorI18n.invalidNameForResource;
+                String nodeName = request.named().getString(registry);
+                request.setError(new RepositorySourceException(getSourceName(),
+                                                               msg.text(getPathAsString(request.under().getPath()),
+                                                                        request.inWorkspace(),
+                                                                        getSourceName(),
+                                                                        nodeName)));
+                return;
+            }
+
+            if (parent != SVNNodeKind.FILE) {
+                I18n msg = SVNRepositoryConnectorI18n.invalidPathForResource;
+                request.setError(new RepositorySourceException(getSourceName(),
+                                                               msg.text(getPathAsString(request.under().getPath()),
+                                                                        request.inWorkspace(),
+                                                                        getSourceName())));
+                return;
+            }
+
+            boolean skipWrite = false;
+            if (parent != SVNNodeKind.NONE || parent != SVNNodeKind.UNKNOWN) {
+                if (request.conflictBehavior().equals(NodeConflictBehavior.APPEND)) {
+                    I18n msg = SVNRepositoryConnectorI18n.sameNameSiblingsAreNotAllowed;
+                    throw new InvalidRequestException(msg.text(this.getSourceName(), newName));
+                } else if (request.conflictBehavior().equals(NodeConflictBehavior.DO_NOT_REPLACE)) {
+                    // TODO check if the file already has content
+                    skipWrite = true;
+                }
+            }
+
+            if (!skipWrite) {
+                Property dataProperty = properties.get(JcrLexicon.DATA);
+                if (dataProperty == null) {
+                    I18n msg = SVNRepositoryConnectorI18n.missingRequiredProperty;
+                    String dataPropName = JcrLexicon.DATA.getString(registry);
+                    request.setError(new RepositorySourceException(getSourceName(),
+                                                                   msg.text(getPathAsString(request.under().getPath()),
+                                                                            request.inWorkspace(),
+                                                                            getSourceName(),
+                                                                            dataPropName)));
+                    return;
+                }
+
+                BinaryFactory binaryFactory = getExecutionContext().getValueFactories().getBinaryFactory();
+                Binary binary = binaryFactory.create(properties.get(JcrLexicon.DATA).getFirstValue());
+                // get old data
+                ByteArrayOutputStream contents = new ByteArrayOutputStream();
+                SVNProperties svnProperties = new SVNProperties();
+                try {
+                    workspaceRoot.getFile(newChildPath, -1, svnProperties, contents);
+                    byte[] oldData = contents.toByteArray();
+                    // modify the empty old data with the new resource
+                    if (oldData != null) {
+                        String rootPath = null;
+                        String fileName = null;
+
+                        Path p = request.under().getPath();
+                        rootPath = getPathAsString(p.getAncestor(1));
+                        fileName = p.getLastSegment().getString(registry);
+
+                        if (request.under().getPath().isRoot()) {
+                            rootPath = "";
+                        }
+
+                        modifyFile(rootPath,
+                                   fileName,
+                                   oldData,
+                                   binary.getBytes(),
+                                   null,
+                                   request.inWorkspace(),
+                                   this.defaultWorkspace);
+                    }
+                } catch (SVNException e) {
+                    I18n msg = SVNRepositoryConnectorI18n.couldNotReadData;
+                    request.setError(new RepositorySourceException(getSourceName(),
+                                                                   msg.text(getPathAsString(request.under().getPath()),
+                                                                            request.inWorkspace(),
+                                                                            getSourceName(),
+                                                                            e.getMessage()), e));
+                    return;
+                }
+            }
+
+        } else if (JcrNtLexicon.FOLDER.equals(primaryType) || primaryType == null) { // Folder
+            ensureValidProperties(request.properties(), ALLOWABLE_PROPERTIES_FOR_FILE_OR_FOLDER);
+            try {
+                String rootDirPath = getPathAsString(request.under().getPath());
+                mkdir(rootDirPath, newName, null, request.inWorkspace(), workspaceRoot);
+            } catch (SVNException e) {
+                I18n msg = SVNRepositoryConnectorI18n.couldNotCreateFile;
+                request.setError(new RepositorySourceException(getSourceName(),
+                                                               msg.text(getPathAsString(request.under().getPath()),
+                                                                        request.inWorkspace(),
+                                                                        getSourceName(),
+                                                                        e.getMessage()), e));
+                return;
+            }
+        } else {
+            I18n msg = SVNRepositoryConnectorI18n.unsupportedPrimaryType;
+            request.setError(new RepositorySourceException(getSourceName(), msg.text(primaryType.getString(registry),
+                                                                                     getPathAsString(request.under().getPath()),
+                                                                                     request.inWorkspace(),
+                                                                                     getSourceName())));
+            return;
+        }
+
+        request.setActualLocationOfNode(actualLocation);
     }
 
     /**
+     * @param workspaceRoot
+     * @param path
+     * @param location
+     * @param inWorkspace
+     * @param request
+     * @return a svn node kind
+     */
+    protected SVNNodeKind getSVNNodeKindFor( SVNRepository workspaceRoot,
+                                             Path path,
+                                             Location location,
+                                             String inWorkspace,
+                                             Request request ) {
+        assert path != null;
+        assert location != null;
+        assert request != null;
+
+        SVNNodeKind rootNode = SVNRepositoryUtil.checkThePath(workspaceRoot, "", -1, getSourceName());
+
+        if (rootNode != SVNNodeKind.DIR) return null;
+
+        if (path.isRoot()) {
+            return rootNode;
+        }
+
+        // See if the path is a "jcr:content" node ...
+        if (path.getLastSegment().getName().equals(JcrLexicon.CONTENT)) {
+            // We only want to use the parent path to find the actual file ...
+            path = path.getParent();
+        }
+        SVNNodeKind kind = rootNode;
+        for (Path.Segment segment : path) {
+            if (segment.getIndex() > 1) {
+                I18n msg = SVNRepositoryConnectorI18n.sameNameSiblingsAreNotAllowed;
+                throw new RepositorySourceException(getSourceName(), msg.text(getSourceName(), request));
+            }
+        }
+
+        String currentPath = getPathAsString(path);
+        if (!this.accessData.getRepositoryRootUrl().equals(inWorkspace)) {
+            if (currentPath.startsWith("/")) {
+                currentPath = currentPath.substring(1);
+            }
+        }
+        kind = SVNRepositoryUtil.checkThePath(workspaceRoot, currentPath, -1, getSourceName());
+
+        if (kind != null) {
+            if (kind == SVNNodeKind.NONE || kind == SVNNodeKind.UNKNOWN) {
+                // Unable to complete the path, so prepare the exception by determining the lowest path that exists ...
+                request.setError(new RepositorySourceException(getSourceName(), " Node kind with path " + currentPath
+                                                                                + " is missing or actually unknown"));
+                return null;
+            }
+        }
+
+        assert kind != null;
+        return kind;
+    }
+
+    private void sameNameSiblingIsNotSupported( Path path,
+                                                CreateNodeRequest request ) {
+        for (Path.Segment segment : path) {
+            // Verify the segment is valid ...
+            if (segment.getIndex() > 1) {
+                I18n msg = SVNRepositoryConnectorI18n.sameNameSiblingsAreNotAllowed;
+                throw new RepositorySourceException(getSourceName(), msg.text(getSourceName(), request));
+            }
+        }
+    }
+
+    /**
      * {@inheritDoc}
      * 
      * @see org.jboss.dna.graph.request.processor.RequestProcessor#process(org.jboss.dna.graph.request.UpdatePropertiesRequest)
@@ -681,44 +993,6 @@
     }
 
     /**
-     * Open the directories where change has to be made.
-     * 
-     * @param editor - abstract editor.
-     * @param rootPath - the pa to open.
-     * @throws SVNException when a error occur.
-     */
-    protected static void openDirectories( ISVNEditor editor,
-                                           String rootPath ) throws SVNException {
-        assert rootPath != null;
-        int pos = rootPath.indexOf('/', 0);
-        while (pos != -1) {
-            String dir = rootPath.substring(0, pos);
-            editor.openDir(dir, -1);
-            pos = rootPath.indexOf('/', pos + 1);
-        }
-        String dir = rootPath.substring(0, rootPath.length());
-        editor.openDir(dir, -1);
-    }
-
-    /**
-     * Close the directories where change was made.
-     * 
-     * @param editor - the abstract editor.
-     * @param path - the directories to open.
-     * @throws SVNException when a error occur.
-     */
-    protected static void closeDirectories( ISVNEditor editor,
-                                            String path ) throws SVNException {
-        int length = path.length() - 1;
-        int pos = path.lastIndexOf('/', length);
-        editor.closeDir();
-        while (pos != -1) {
-            editor.closeDir();
-            pos = path.lastIndexOf('/', pos - 1);
-        }
-    }
-
-    /**
      * Get the last revision.
      * 
      * @param repos
@@ -736,123 +1010,159 @@
     }
 
     /**
-     * Add directory in a repository
+     * Create a directory .
      * 
-     * @param repository - the repository.
-     * @param root - the root path has to exist.
-     * @param child - new path to be added.
-     * @param message - information about the change action.
-     * @throws SVNException when a error occur.
+     * @param rootDirPath - the root directory where the created directory will reside
+     * @param childDirPath - the name of the created directory.
+     * @param comment - comment for the creation.
+     * @param inWorkspace
+     * @param currentRepository
+     * @throws SVNException - if during the creation, there is an error.
      */
-    protected void addDirEntry( SVNRepository repository,
-                                String root,
-                                String child,
-                                String message ) throws SVNException {
-        assert root.trim().length() != 0;
-        SVNNodeKind rootKind = repository.checkPath(root, -1);
-        if (rootKind == SVNNodeKind.UNKNOWN) {
+    private void mkdir( String rootDirPath,
+                        String childDirPath,
+                        String comment,
+                        String inWorkspace,
+                        SVNRepository currentRepository ) throws SVNException {
+
+        String tempParentPath = rootDirPath;
+        if (!this.accessData.getRepositoryRootUrl().equals(inWorkspace)) {
+            if (!tempParentPath.equals("/") && tempParentPath.startsWith("/")) {
+                tempParentPath = tempParentPath.substring(1);
+            } else if (tempParentPath.equals("/")) {
+                tempParentPath = "";
+            }
+        }
+        String checkPath = tempParentPath.length() == 0 ? childDirPath : tempParentPath + "/" + childDirPath;
+        SVNNodeKind nodeKind = null;
+        try {
+            nodeKind = currentRepository.checkPath(checkPath, -1);
+        } catch (SVNException e) {
             SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
-                                                         "path with name '{0}' is unknown in the repository",
-                                                         root);
+                                                         "May be a Connecting problem to the repository or a user's authentication failure: {0}",
+                                                         e.getMessage());
             throw new SVNException(err);
-        } else if (rootKind == SVNNodeKind.NONE) {
+        }
+
+        if (nodeKind != null && nodeKind == SVNNodeKind.NONE) {
+            ScmAction addNodeAction = addDirectory(rootDirPath, childDirPath);
+            SVNActionExecutor executor = new SVNActionExecutor(currentRepository);
+            comment = comment == null ? "Create a new file " + childDirPath : comment;
+            executor.execute(addNodeAction, comment);
+        } else {
             SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
-                                                         "path with name '{0}' is missing in the repository",
-                                                         root);
+                                                         "Node with name '{0}' can't be created",
+                                                         childDirPath);
             throw new SVNException(err);
-        } else if (rootKind == SVNNodeKind.FILE) {
-            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
-                                                         "path with name '{0}' is a file, you need a directory",
-                                                         root);
-            throw new SVNException(err);
-        } else if (rootKind == SVNNodeKind.DIR) {
-            ISVNEditor editor = repository.getCommitEditor(message, null, true, null);
-            if (root.length() == 1 && root.charAt(0) == '/') {
-                addProcess(repository, editor, root, "", child);
-            } else {
-                String rootPath = root.substring(1);
-                addProcess(repository, editor, rootPath, null, child);
-            }
         }
     }
 
-    private void addProcess( SVNRepository repos,
-                             ISVNEditor editor,
-                             String rootPath,
-                             String editedRoot,
-                             String childSegmentName ) throws SVNException {
-        openDirectories(editor, editedRoot);
-        // test if so a directory does not exist.
-        SVNNodeKind childKind = repos.checkPath(childSegmentName, -1);
-        if (childKind == SVNNodeKind.NONE) {
-            editor.addDir(childSegmentName, null, -1);
-            closeDirectories(editor, childSegmentName);
-            if (editedRoot != null) {
-                closeDirectories(editor, editedRoot);
-            } else {
-                closeDirectories(editor, rootPath);
-            }
+    /**
+     * Create a file.
+     * 
+     * @param rootDirPath
+     * @param childFilePath
+     * @param content
+     * @param comment
+     * @param inWorkspace
+     * @param currentRepository
+     * @throws SVNException
+     */
+    public void newFile( String rootDirPath,
+                         String childFilePath,
+                         byte[] content,
+                         String comment,
+                         String inWorkspace,
+                         SVNRepository currentRepository ) throws SVNException {
 
-        } else {
-            closeDirectories(editor, childSegmentName);
-            if (editedRoot != null) {
-                closeDirectories(editor, editedRoot);
-            } else {
-                closeDirectories(editor, rootPath);
+        String tempParentPath = rootDirPath;
+        if (!this.accessData.getRepositoryRootUrl().equals(inWorkspace)) {
+            if (!tempParentPath.equals("/") && tempParentPath.startsWith("/")) {
+                tempParentPath = tempParentPath.substring(1);
             }
         }
-    }
+        String checkPath = tempParentPath + "/" + childFilePath;
+        SVNNodeKind nodeKind = null;
+        try {
+            nodeKind = currentRepository.checkPath(checkPath, -1);
+        } catch (SVNException e) {
+            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
+                                                         "May be a Connecting problem to the repository or a user's authentication failure: {0}",
+                                                         e.getMessage());
+            throw new SVNException(err);
+        }
 
-    /**
-     * Create a directory .
-     * 
-     * @param repos
-     * @param root - the root directory where the created directory will reside
-     * @param childName - the name of the created directory.
-     * @param message - comment for the creation.
-     * @throws SVNException - if during the creation, there is an error.
-     */
-    @SuppressWarnings( "unused" )
-    private void mkdir( SVNRepository repos,
-                        String root,
-                        String childName,
-                        String message ) throws SVNException {
-        SVNNodeKind childKind = repos.checkPath(childName, -1);
-        if (childKind == SVNNodeKind.NONE) {
-            ScmAction addNodeAction = addDirectory(root, childName);
-            SVNActionExecutor executor = new SVNActionExecutor(repos);
-            executor.execute(addNodeAction, message);
+        if (nodeKind != null && nodeKind == SVNNodeKind.NONE) {
+            ScmAction addFileNodeAction = addFile(rootDirPath, childFilePath, content);
+            SVNActionExecutor executor = new SVNActionExecutor(currentRepository);
+            comment = comment == null ? "Create a new file " + childFilePath : comment;
+            executor.execute(addFileNodeAction, comment);
         } else {
-            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "Item with name '{0}' can't be created", childName);
+            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
+                                                         "Item with name '{0}' can't be created (already exist)",
+                                                         childFilePath);
             throw new SVNException(err);
         }
     }
 
     /**
-     * Create a file.
+     * Modify a file
      * 
-     * @param path
-     * @param file
-     * @param content
-     * @param message
+     * @param rootPath
+     * @param fileName
+     * @param oldData
+     * @param newData
+     * @param comment
+     * @param inWorkspace
+     * @param currentRepository
      * @throws SVNException
      */
-    @SuppressWarnings( "unused" )
-    private void newFile( String path,
-                          String file,
-                          byte[] content,
-                          String message ) throws SVNException {
-        SVNNodeKind childKind = defaultWorkspace.checkPath(file, -1);
-        if (childKind == SVNNodeKind.NONE) {
-            ScmAction addFileNodeAction = addFile(path, file, content);
-            SVNActionExecutor executor = new SVNActionExecutor(defaultWorkspace);
-            executor.execute(addFileNodeAction, message);
-        } else {
-            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN,
-                                                         "Item with name '{0}' can't be created (already exist)",
-                                                         file);
+    private void modifyFile( String rootPath,
+                             String fileName,
+                             byte[] oldData,
+                             byte[] newData,
+                             String comment,
+                             String inWorkspace,
+                             SVNRepository currentRepository ) throws SVNException {
+        assert rootPath != null;
+        assert fileName != null;
+        assert oldData != null;
+        assert inWorkspace != null;
+        assert currentRepository != null;
+
+        try {
+
+            if (!this.accessData.getRepositoryRootUrl().equals(inWorkspace)) {
+                if (rootPath.equals("/")) {
+                    rootPath = "";
+                } else {
+                    rootPath = rootPath.substring(1) + "/";
+                }
+            } else {
+                if (!rootPath.equals("/")) {
+                    rootPath = rootPath + "/";
+                }
+            }
+            String path = rootPath + fileName;
+
+            SVNNodeKind nodeKind = currentRepository.checkPath(path, -1);
+            if (nodeKind == SVNNodeKind.NONE || nodeKind == SVNNodeKind.UNKNOWN) {
+                SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND,
+                                                             "Item with name '{0}' can't be found",
+                                                             path);
+                throw new SVNException(err);
+            }
+
+            ScmAction modifyFileAction = mergeFile(rootPath, fileName, oldData, newData);
+            SVNActionExecutor executor = new SVNActionExecutor(currentRepository);
+            comment = comment == null ? "modify the " + fileName : comment;
+            executor.execute(modifyFileAction, comment);
+
+        } catch (SVNException e) {
+            SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNKNOWN, "This error is appeared: '{0}'", e.getMessage());
             throw new SVNException(err);
         }
+
     }
 
     /**
@@ -879,6 +1189,18 @@
     /**
      * {@inheritDoc}
      * 
+     * @see org.jboss.dna.connector.scm.ScmActionFactory#mergeFile(java.lang.String, java.lang.String, byte[], byte[])
+     */
+    public ScmAction mergeFile( String rootPath,
+                                String fileName,
+                                byte[] oldData,
+                                byte[] newData ) {
+        return new MergeFile(rootPath, fileName, oldData, newData);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
      * @see org.jboss.dna.connector.scm.ScmActionFactory#copyDirectory(java.lang.String, java.lang.String, long)
      */
     public ScmAction copyDirectory( String path,
@@ -906,66 +1228,6 @@
         return null;
     }
 
-    /**
-     * root should be the last, previously created, parent folder. Each directory in the path will be created.
-     */
-    public static class AddDirectory implements ScmAction {
-        private String root;
-        private String path;
-
-        public AddDirectory( String root,
-                             String path ) {
-            this.root = root;
-            this.path = path;
-        }
-
-        public void applyAction( Object context ) throws SVNException {
-
-            ISVNEditor editor = (ISVNEditor)context;
-
-            openDirectories(editor, this.root);
-            String[] paths = this.path.split("/");
-            String newPath = this.root;
-            for (int i = 0, length = paths.length; i < length; i++) {
-                newPath = (newPath.length() != 0) ? newPath + "/" + paths[i] : paths[i];
-
-                editor.addDir(newPath, null, -1);
-            }
-
-            closeDirectories(editor, path);
-            closeDirectories(editor, this.root);
-        }
-    }
-
-    public static class AddFile implements ScmAction {
-        private String path;
-        private String file;
-        private byte[] content;
-
-        public AddFile( String path,
-                        String file,
-                        byte[] content ) {
-            this.path = path;
-            this.file = file;
-            this.content = content;
-        }
-
-        public void applyAction( Object context ) throws Exception {
-            ISVNEditor editor = (ISVNEditor)context;
-            openDirectories(editor, path);
-
-            editor.addFile(path + "/" + file, null, -1);
-            editor.applyTextDelta(path + "/" + file, null);
-            SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
-            String checksum = deltaGenerator.sendDelta(path + "/" + file, new ByteArrayInputStream(this.content), editor, true);
-            editor.closeFile(path + "/" + file, checksum);
-
-            closeDirectories(editor, path);
-
-        }
-
-    }
-
     @SuppressWarnings( "unused" )
     private byte[] getContent( Object[] objs ) {
         byte[] content = null;
@@ -995,11 +1257,6 @@
                 I18n msg = SVNRepositoryConnectorI18n.sameNameSiblingsAreNotAllowed;
                 throw new RepositorySourceException(getSourceName(), msg.text(getSourceName(), request));
             }
-            // TODO
-            // if (!segment.getName().getNamespaceUri().equals(defaultNamespaceUri)) {
-            // I18n msg = SVNRepositoryConnectorI18n.onlyTheDefaultNamespaceIsAllowed;
-            // throw new RepositorySourceException(getSourceName(), msg.text(getSourceName(), request));
-            // }
         }
     }
 
@@ -1046,4 +1303,30 @@
         }
         return kind;
     }
+
+    /**
+     * Checks that the collection of {@code properties} only contains properties with allowable names.
+     * 
+     * @param properties
+     * @param validPropertyNames
+     * @throws RepositorySourceException if {@code properties} contains a
+     * @see #ALLOWABLE_PROPERTIES_FOR_CONTENT
+     * @see #ALLOWABLE_PROPERTIES_FOR_FILE_OR_FOLDER
+     */
+    protected void ensureValidProperties( Collection<Property> properties,
+                                          Set<Name> validPropertyNames ) {
+        List<String> invalidNames = new LinkedList<String>();
+        NamespaceRegistry registry = getExecutionContext().getNamespaceRegistry();
+
+        for (Property property : properties) {
+            if (!validPropertyNames.contains(property.getName())) {
+                invalidNames.add(property.getName().getString(registry));
+            }
+        }
+
+        if (!invalidNames.isEmpty()) {
+            throw new RepositorySourceException(this.getSourceName(),
+                                                SVNRepositoryConnectorI18n.invalidPropertyNames.text(invalidNames.toString()));
+        }
+    }
 }

Modified: trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java	2009-12-29 22:46:08 UTC (rev 1489)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java	2009-12-29 22:46:45 UTC (rev 1490)
@@ -62,7 +62,7 @@
      * The first serialized version of this source. Version {@value} .
      */
     private static final long serialVersionUID = 1L;
-
+    
     protected static final String SOURCE_NAME = "sourceName";
     protected static final String SVN_REPOSITORY_ROOT_URL = "repositoryRootURL";
     protected static final String SVN_USERNAME = "username";
@@ -165,7 +165,7 @@
      * @param url - the url location.
      * @throws IllegalArgumentException If svn url is null or empty
      */
-    public void setRepositoryRootURL( String url ) {
+    public synchronized void setRepositoryRootURL( String url ) {
         CheckArg.isNotEmpty(url, "RepositoryRootURL");
         this.repositoryRootURL = url;
     }
@@ -177,7 +177,7 @@
     /**
      * @param username
      */
-    public void setUsername( String username ) {
+    public synchronized void setUsername( String username ) {
         this.username = username;
     }
 
@@ -188,7 +188,7 @@
     /**
      * @param password
      */
-    public void setPassword( String password ) {
+    public synchronized void setPassword( String password ) {
         this.password = password;
     }
 
@@ -278,6 +278,29 @@
                                                         capabilities.supportsEvents(), allowWorkspaceCreation,
                                                         capabilities.supportsReferences());
     }
+    
+    /**
+     * Get whether this source allows updates.
+     * 
+     * @return true if this source allows updates by clients, or false if no updates are allowed
+     * @see #setUpdatesAllowed(boolean)
+     */
+    public boolean areUpdatesAllowed() {
+        return capabilities.supportsUpdates();
+    }
+    
+    /**
+     * Set whether this source allows updates to data within workspaces
+     * 
+     * @param allowUpdates true if this source allows updates to data within workspaces clients, or false if updates are not
+     *        allowed.
+     * @see #areUpdatesAllowed()
+     */
+    public synchronized void setUpdatesAllowed( boolean allowUpdates ) {
+        capabilities = new RepositorySourceCapabilities(capabilities.supportsSameNameSiblings(), allowUpdates,
+                                                        capabilities.supportsEvents(), capabilities.supportsCreatingWorkspaces(),
+                                                        capabilities.supportsReferences());
+    }
 
     /**
      * {@inheritDoc}

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-12-29 22:46:08 UTC (rev 1489)
+++ trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositoryUtil.java	2009-12-29 22:46:45 UTC (rev 1490)
@@ -1,3 +1,26 @@
+/*
+ * 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 java.util.Collection;
@@ -66,7 +89,7 @@
             kind = repository.checkPath(path, revisionNumber);
 
         } catch (SVNException e) {
-            throw new RepositorySourceException(sourceName, e.getMessage());
+            return null;
         }
         return kind;
     }



More information about the dna-commits mailing list