This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-ide-tooling.git


The following commit(s) were added to refs/heads/master by this push:
     new 9933d021 SLING-7599 - Stop using String for paths (#36)
9933d021 is described below

commit 9933d021581102b433080f9e5de3d0a6fc1621ff
Author: Robert Munteanu <[email protected]>
AuthorDate: Fri May 23 15:57:36 2025 +0200

    SLING-7599 - Stop using String for paths (#36)
    
    Introduce RepositoryPath and use throughout the repository.
---
 .../org/apache/sling/ide/cli/impl/ContentSync.java |  3 +-
 .../core/internal/SlingLaunchpadBehaviour.java     |  8 +-
 .../test/impl/DefaultCommandFactoryImplTest.java   | 11 ++-
 .../test/impl/JcrContentContentProviderTest.java   |  4 +-
 .../sling/ide/test/impl/helpers/SpyCommand.java    |  7 +-
 .../sling/ide/test/impl/helpers/SpyRepository.java |  9 ++-
 .../ui/internal/ImportRepositoryContentAction.java | 30 +++----
 .../sling/ide/eclipse/ui/nav/model/JcrNode.java    |  5 +-
 .../java/org/apache/sling/ide/filter/Filter.java   |  4 +-
 .../apache/sling/ide/filter/IgnoredResources.java  |  6 +-
 .../ide/serialization/SerializationManager.java    |  3 +-
 .../sling/ide/sync/content/WorkspacePath.java      |  1 +
 .../content/impl/DefaultSyncCommandFactory.java    | 10 +--
 .../org/apache/sling/ide/transport/Command.java    |  2 +-
 .../org/apache/sling/ide/transport/Repository.java |  8 +-
 .../apache/sling/ide/transport/RepositoryPath.java | 92 ++++++++++++++++++++++
 .../apache/sling/ide/transport/ResourceProxy.java  | 46 +++--------
 .../sling/ide/transport/impl/DefaultBatcher.java   | 10 +--
 .../java/org/apache/sling/ide/util/PathUtil.java   | 40 ++++++++++
 .../org/apache/sling/ide/util/package-info.java    | 19 -----
 .../sling/ide/filter/IgnoredResourcesTest.java     | 17 ++--
 .../ide/serialization/NodeTypeResourceBuilder.java |  9 +--
 .../sling/ide/serialization/StubRepository.java    |  9 ++-
 .../sling/ide/transport/ResourceProxyTest.java     | 46 +++++------
 .../sling/ide/impl/vlt/AddOrUpdateNodeCommand.java | 26 +++---
 .../sling/ide/impl/vlt/DeleteNodeCommand.java      |  7 +-
 .../apache/sling/ide/impl/vlt/GetNodeCommand.java  |  5 +-
 .../sling/ide/impl/vlt/GetNodeContentCommand.java  |  5 +-
 .../org/apache/sling/ide/impl/vlt/JcrCommand.java  | 11 ++-
 .../sling/ide/impl/vlt/ListChildrenCommand.java    |  5 +-
 .../apache/sling/ide/impl/vlt/ListTreeCommand.java |  5 +-
 .../ide/impl/vlt/ReorderChildNodesCommand.java     | 15 ++--
 .../sling/ide/impl/vlt/VltNodeTypeFactory.java     | 12 +--
 .../apache/sling/ide/impl/vlt/VltRepository.java   | 11 +--
 .../sling/ide/impl/vlt/filter/VltFilter.java       | 13 ++-
 .../serialization/ResourceProxyParserHandler.java  |  5 +-
 .../serialization/VltSerializationDataBuilder.java | 10 +--
 .../vlt/serialization/VltSerializationManager.java |  9 ++-
 .../ide/impl/vlt/AddOrUpdateNodeCommandIT.java     | 11 +--
 .../ide/impl/vlt/ReorderChildNodesCommandIT.java   |  3 +-
 .../sling/ide/impl/vlt/filter/VltFilterTest.java   | 21 ++---
 .../ResourceProxyParserHandlerTest.java            | 17 ++--
 .../serialization/VltSerializationManagerTest.java |  9 ++-
 .../ide/impl/vlt/transport/DefaultBatcherTest.java | 41 +++++-----
 .../content/sync/fs/impl/MockFilterLocator.java    |  3 +-
 45 files changed, 375 insertions(+), 268 deletions(-)

diff --git 
a/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java 
b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java
index 5daccfaf..baa58b76 100644
--- a/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java
+++ b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java
@@ -36,6 +36,7 @@ import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryFactory;
 import org.apache.sling.ide.transport.RepositoryInfo;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 
@@ -76,7 +77,7 @@ public class ContentSync {
         
         Repository repo = repoFactory.connectRepository(new 
RepositoryInfo(cfg.username(), cfg.password(), 
URI.create(cfg.repositoryUrl())));
         
-        repo.newListChildrenNodeCommand("/").execute();
+        repo.newListChildrenNodeCommand(new RepositoryPath("/")).execute();
         
         logger.trace("Connected to {0} ", repo.getRepositoryInfo());
         
diff --git 
a/eclipse/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
 
b/eclipse/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
index 0812f3db..f25794cb 100644
--- 
a/eclipse/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
+++ 
b/eclipse/eclipse-core/src/org/apache/sling/ide/eclipse/core/internal/SlingLaunchpadBehaviour.java
@@ -42,6 +42,7 @@ import org.apache.sling.ide.transport.Batcher;
 import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryInfo;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.Result;
 import org.eclipse.core.resources.IFile;
@@ -63,7 +64,6 @@ import org.eclipse.wst.server.core.IServer;
 import org.eclipse.wst.server.core.model.IModuleResource;
 import org.eclipse.wst.server.core.model.IModuleResourceDelta;
 import org.eclipse.wst.server.core.model.ServerBehaviourDelegate;
-import org.osgi.framework.Constants;
 import org.osgi.framework.Version;
 
 public class SlingLaunchpadBehaviour extends 
ServerBehaviourDelegateWithModulePublishSupport {
@@ -128,7 +128,7 @@ public class SlingLaunchpadBehaviour extends 
ServerBehaviourDelegateWithModulePu
        
                    } else {
                        
-                       Command<ResourceProxy> command = 
repository.newListChildrenNodeCommand("/");
+                       Command<ResourceProxy> command = 
repository.newListChildrenNodeCommand(new RepositoryPath("/"));
                        result = command.execute();
                        success = result.isSuccess();
                        
@@ -592,9 +592,9 @@ public class SlingLaunchpadBehaviour extends 
ServerBehaviourDelegateWithModulePu
 
     private IResource getResource(IModuleResource resource) {
 
-        IResource file = (IFile) resource.getAdapter(IFile.class);
+        IResource file = resource.getAdapter(IFile.class);
         if (file == null) {
-            file = (IFolder) resource.getAdapter(IFolder.class);
+            file = resource.getAdapter(IFolder.class);
         }
 
         if (file == null) {
diff --git 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/DefaultCommandFactoryImplTest.java
 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/DefaultCommandFactoryImplTest.java
index 7c7c89af..3d4dbf4d 100644
--- 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/DefaultCommandFactoryImplTest.java
+++ 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/DefaultCommandFactoryImplTest.java
@@ -39,7 +39,6 @@ import org.apache.sling.ide.test.impl.helpers.SpyRepository;
 import org.apache.sling.ide.test.impl.helpers.TemporaryProject;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.ResourceProxy;
-import org.apache.sling.ide.util.PathUtil;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.NullProgressMonitor;
@@ -106,14 +105,14 @@ public class DefaultCommandFactoryImplTest {
         SpyCommand<?> command = (SpyCommand<?>) 
factory.newCommandForAddedOrUpdatedResource(spyRepo,
                 
EclipseResources.create(contentProject.findMember("jcr_root/content/test-root/nested/gitignore")));
         assertThat("command.path", command.getPath(), nullValue());
-        assertThat("command.resource.path", 
command.getResourceProxy().getPath(), 
equalTo("/content/test-root/nested/gitignore"));
+        assertThat("command.resource.path", 
command.getResourceProxy().getPath().asString(), 
equalTo("/content/test-root/nested/gitignore"));
         assertThat("command.resource.properties", 
command.getResourceProxy().getProperties(),
                 equalTo(singletonMap("jcr:primaryType", (Object) "nt:file")));
         assertThat("command.kind", command.getSpyKind(), 
equalTo(SpyCommand.Kind.ADD_OR_UPDATE));
         
         command = (SpyCommand<?>) factory.newCommandForRemovedResource(spyRepo,
                 
EclipseResources.create(contentProject.findMember("jcr_root/content/test-root/nested/gitignore")));
-        assertThat("command.path", command.getPath(), 
equalTo("/content/test-root/nested/gitignore"));
+        assertThat("command.path", command.getPath().asString(), 
equalTo("/content/test-root/nested/gitignore"));
         assertThat("command.kind", command.getSpyKind(), 
equalTo(SpyCommand.Kind.DELETE));
     }
 
@@ -129,7 +128,7 @@ public class DefaultCommandFactoryImplTest {
                 
EclipseResources.create(contentProject.findMember("jcr_root/content/test-root")));
 
         assertThat("command.path", command.getPath(), nullValue());
-        assertThat("command.resource.path", 
command.getResourceProxy().getPath(), equalTo("/content/test-root"));
+        assertThat("command.resource.path", 
command.getResourceProxy().getPath().asString(), equalTo("/content/test-root"));
         assertThat("command.resource.properties", 
command.getResourceProxy().getProperties(),
                 equalTo(singletonMap("jcr:primaryType", (Object) 
"nt:folder")));
         assertThat("command.fileinfo", command.getFileInfo(), nullValue());
@@ -152,7 +151,7 @@ public class DefaultCommandFactoryImplTest {
         props.put("jcr:title", "Some Folder");
 
         assertThat("command.path", command.getPath(), nullValue());
-        assertThat("command.resource.path", 
command.getResourceProxy().getPath(), equalTo("/content/test-root/nested"));
+        assertThat("command.resource.path", 
command.getResourceProxy().getPath().asString(), 
equalTo("/content/test-root/nested"));
         assertThat("command.resource.properties", 
command.getResourceProxy().getProperties(), equalTo(props));
         assertThat("command.fileinfo", command.getFileInfo(), nullValue());
         assertThat("command.kind", command.getSpyKind(), 
equalTo(SpyCommand.Kind.ADD_OR_UPDATE));
@@ -207,6 +206,6 @@ public class DefaultCommandFactoryImplTest {
         List<ResourceProxy> children = 
command.getResourceProxy().getChildren();
 
         assertThat("command.resource.children.size", children.size(), 
equalTo(3));
-        assertThat("command.resource.children[2].name", 
PathUtil.getName(children.get(2).getPath()), equalTo("folder2"));
+        assertThat("command.resource.children[2].name", 
children.get(2).getPath().getName(), equalTo("folder2"));
     }
 }
diff --git 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/JcrContentContentProviderTest.java
 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/JcrContentContentProviderTest.java
index 037b4444..48fd6315 100644
--- 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/JcrContentContentProviderTest.java
+++ 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/JcrContentContentProviderTest.java
@@ -30,7 +30,7 @@ import org.apache.sling.ide.eclipse.ui.nav.model.SyncDir;
 import org.apache.sling.ide.test.impl.helpers.DisableDebugStatusHandlers;
 import org.apache.sling.ide.test.impl.helpers.ProjectAdapter;
 import org.apache.sling.ide.test.impl.helpers.TemporaryProject;
-import org.apache.sling.ide.util.PathUtil;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.Path;
@@ -176,7 +176,7 @@ public class JcrContentContentProviderTest {
             for ( Object child : children ) {
                 JcrNode childNode = (JcrNode) child;
                 // childNode.getName() does not seem to be usable here, so 
relying on the path
-                String childName = PathUtil.getName(childNode.getJcrPath());
+                String childName = new 
RepositoryPath(childNode.getJcrPath()).getName();
                 if ( childName.equals(expectedChildName)) {
                     current = childNode;
                     continue segments;
diff --git 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyCommand.java
 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyCommand.java
index 4917ab08..dd0ef3b6 100644
--- 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyCommand.java
+++ 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyCommand.java
@@ -23,6 +23,7 @@ import java.util.Set;
 import org.apache.sling.ide.sync.content.WorkspaceFile;
 import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.Repository.CommandExecutionFlag;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.Result;
 
@@ -41,11 +42,11 @@ public class SpyCommand<T> implements Command<T> {
 
     private final ResourceProxy resourceProxy;
     private final WorkspaceFile fileInfo;
-    private final String path;
+    private final RepositoryPath path;
     private final SpyCommand.Kind kind;
     private final EnumSet<CommandExecutionFlag> flags;
 
-    public SpyCommand(ResourceProxy resourceProxy, WorkspaceFile fileInfo, 
String path, SpyCommand.Kind kind,
+    public SpyCommand(ResourceProxy resourceProxy, WorkspaceFile fileInfo, 
RepositoryPath path, SpyCommand.Kind kind,
             CommandExecutionFlag... flags) {
         this.resourceProxy = resourceProxy;
         this.fileInfo = fileInfo;
@@ -61,7 +62,7 @@ public class SpyCommand<T> implements Command<T> {
     }
 
     @Override
-    public String getPath() {
+    public RepositoryPath getPath() {
         return path;
     }
 
diff --git 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyRepository.java
 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyRepository.java
index ad02b714..1b78a361 100644
--- 
a/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyRepository.java
+++ 
b/eclipse/eclipse-test/src/org/apache/sling/ide/test/impl/helpers/SpyRepository.java
@@ -23,6 +23,7 @@ import 
org.apache.sling.ide.transport.FallbackNodeTypeRegistry;
 import org.apache.sling.ide.transport.NodeTypeRegistry;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryInfo;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 /**
@@ -50,22 +51,22 @@ public class SpyRepository implements Repository {
     }
 
     @Override
-    public Command<Void> newDeleteNodeCommand(String path) {
+    public Command<Void> newDeleteNodeCommand(RepositoryPath path) {
         return new SpyCommand<>(null, null, path, SpyCommand.Kind.DELETE);
     }
 
     @Override
-    public Command<ResourceProxy> newListChildrenNodeCommand(String path) {
+    public Command<ResourceProxy> newListChildrenNodeCommand(RepositoryPath 
path) {
         throw new UnsupportedOperationException("Not implemented");
     }
 
     @Override
-    public Command<ResourceProxy> newGetNodeContentCommand(String path) {
+    public Command<ResourceProxy> newGetNodeContentCommand(RepositoryPath 
path) {
         throw new UnsupportedOperationException("Not implemented");
     }
 
     @Override
-    public Command<byte[]> newGetNodeCommand(String path) {
+    public Command<byte[]> newGetNodeCommand(RepositoryPath path) {
         throw new UnsupportedOperationException("Not implemented");
     }
 
diff --git 
a/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/internal/ImportRepositoryContentAction.java
 
b/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/internal/ImportRepositoryContentAction.java
index f7d1fa4f..4b21f2b1 100644
--- 
a/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/internal/ImportRepositoryContentAction.java
+++ 
b/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/internal/ImportRepositoryContentAction.java
@@ -28,7 +28,6 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.jackrabbit.util.Text;
 import org.apache.sling.ide.eclipse.core.EclipseResources;
 import org.apache.sling.ide.eclipse.core.ProjectUtil;
 import org.apache.sling.ide.eclipse.core.ResourceUtil;
@@ -45,9 +44,11 @@ import org.apache.sling.ide.serialization.SerializationKind;
 import org.apache.sling.ide.serialization.SerializationKindManager;
 import org.apache.sling.ide.serialization.SerializationManager;
 import org.apache.sling.ide.sync.content.SyncCommandFactory;
+import org.apache.sling.ide.sync.content.WorkspacePath;
 import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryException;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceAndInfo;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.Result;
@@ -150,8 +151,10 @@ public class ImportRepositoryContentAction {
             recordNotIgnoredResources();
 
             ProgressUtils.advance(monitor, 1);
+            
+            RepositoryPath repositoryPath = 
serializationManager.getRepositoryPath(new 
WorkspacePath(repositoryImportRoot.toPortableString()));
 
-            crawlChildrenAndImport(repositoryImportRoot.toPortableString());
+            crawlChildrenAndImport(repositoryPath);
 
             removeNotIgnoredAndNotUpdatedResources(new NullProgressMonitor());
 
@@ -205,7 +208,7 @@ public class ImportRepositoryContentAction {
                         return true;
                     }
 
-                    String repositoryPath = rai.getResource().getPath();
+                    RepositoryPath repositoryPath = 
rai.getResource().getPath();
 
                     FilterResult filterResult = filter.filter(repositoryPath);
 
@@ -252,12 +255,11 @@ public class ImportRepositoryContentAction {
      * @throws IOException
      */
     // TODO: This probably should be pushed into the service layer
-    private void crawlChildrenAndImport(String path)
+    private void crawlChildrenAndImport(RepositoryPath repositoryPath)
             throws RepositoryException, CoreException, IOException, 
SerializationException {
 
-        logger.trace("crawlChildrenAndImport({0},  {1}, {2}, {3}", repository, 
path, project, projectRelativePath);
-
-        ResourceProxy resource = 
executeCommand(repository.newListChildrenNodeCommand(path));
+        logger.trace("crawlChildrenAndImport({0},  {1}, {2}, {3}", repository, 
repositoryPath, project, projectRelativePath);
+        ResourceProxy resource = 
executeCommand(repository.newListChildrenNodeCommand(repositoryPath));
         
         SerializationData serializationData = 
builder.buildSerializationData(contentSyncRoot, resource);
         logger.trace("For resource at path {0} got serialization data {1}", 
resource.getPath(), serializationData);
@@ -270,7 +272,7 @@ public class ImportRepositoryContentAction {
        
                switch (serializationData.getSerializationKind()) {
                    case FILE: {
-                       byte[] contents = 
executeCommand(repository.newGetNodeCommand(path));
+                       byte[] contents = 
executeCommand(repository.newGetNodeCommand(repositoryPath));
                     createFile(project, getPathForPlainFileNode(resource, 
serializationFolderPath), contents);
        
                        if (serializationData.hasContents()) {
@@ -293,7 +295,7 @@ public class ImportRepositoryContentAction {
 
                                 if (reloadedChildResource.getChildren().size() 
!= 0) {
 
-                                    String pathName = 
Text.getName(reloadedChildResource.getPath());
+                                    String pathName = 
reloadedChildResource.getPath().getName();
                                     pathName = 
serializationManager.getLocalName(pathName);
                                     createFolder(project, 
serializationFolderPath.append(pathName));
 
@@ -315,7 +317,7 @@ public class ImportRepositoryContentAction {
 
                     IFolder folder = createFolder(project, 
serializationFolderPath);
 
-                    parseIgnoreFiles(folder, path);
+                    parseIgnoreFiles(folder, repositoryPath.asString());
 
                        if (serializationData.hasContents()) {
                         createFile(project, 
serializationFolderPath.append(serializationData.getFileName()),
@@ -377,12 +379,12 @@ public class ImportRepositoryContentAction {
 
         // TODO - can we just use the serializationFolderPath ?
 
-        String name = 
serializationManager.getLocalName(Text.getName(resource.getPath()));
+        String name = 
serializationManager.getLocalName(resource.getPath().getName());
 
         return serializationFolderPath.removeLastSegments(1).append(name);
     }
 
-    private void parseIgnoreFiles(IFolder folder, String path) throws 
IOException, CoreException {
+    private void parseIgnoreFiles(IFolder folder, String repositoryPath) 
throws IOException, CoreException {
         // TODO - the parsing should be extracted
         IResource vltIgnore = folder.findMember(".vltignore");
         if (vltIgnore != null && vltIgnore instanceof IFile) {
@@ -393,8 +395,8 @@ public class ImportRepositoryContentAction {
             try (InputStream contents = ((IFile) vltIgnore).getContents()) {
                 List<String> ignoreLines = IOUtils.readLines(contents);
                 for (String ignoreLine : ignoreLines) {
-                    logger.trace("Registering ignore rule {0}:{1}", path, 
ignoreLine);
-                    ignoredResources.registerRegExpIgnoreRule(path, 
ignoreLine);
+                    logger.trace("Registering ignore rule {0}:{1}", 
repositoryPath, ignoreLine);
+                    ignoredResources.registerRegExpIgnoreRule(repositoryPath, 
ignoreLine);
                 }
             }
         }
diff --git 
a/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/nav/model/JcrNode.java 
b/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/nav/model/JcrNode.java
index 65cb7275..735fadc8 100644
--- 
a/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/nav/model/JcrNode.java
+++ 
b/eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/nav/model/JcrNode.java
@@ -18,7 +18,6 @@ package org.apache.sling.ide.eclipse.ui.nav.model;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -49,10 +48,10 @@ import org.apache.sling.ide.serialization.SerializationKind;
 import org.apache.sling.ide.serialization.SerializationKindManager;
 import org.apache.sling.ide.serialization.SerializationManager;
 import org.apache.sling.ide.sync.content.WorkspaceFile;
-import org.apache.sling.ide.sync.content.WorkspaceResource;
 import org.apache.sling.ide.transport.NodeTypeRegistry;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryException;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -1089,7 +1088,7 @@ public class JcrNode implements IAdaptable {
         try {
             final IProject project = getProject();
             final Filter filter = ProjectUtil.loadFilter(project);
-            final String relativeFilePath = getJcrPath();
+            final RepositoryPath relativeFilePath = new 
RepositoryPath(getJcrPath());
 //            final Repository repository = 
Activator.getDefault().getRepositoryFactory().newRepository(null);//ServerUtil.getRepository(null,
 null);
 //            final RepositoryInfo repositoryInfo = 
repository.getRepositoryInfo();
 //            if (repositoryInfo==null) {
diff --git a/shared/api/src/main/java/org/apache/sling/ide/filter/Filter.java 
b/shared/api/src/main/java/org/apache/sling/ide/filter/Filter.java
index 0dd41919..1dc71e78 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/filter/Filter.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/filter/Filter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.sling.ide.filter;
 
+import org.apache.sling.ide.transport.RepositoryPath;
+
 public interface Filter {
 
     /**
@@ -25,5 +27,5 @@ public interface Filter {
      * 
      * @return the filter result, never <code>null</code>
      */
-    FilterResult filter(String repositoryPath);
+    FilterResult filter(RepositoryPath repositoryPath);
 }
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/filter/IgnoredResources.java 
b/shared/api/src/main/java/org/apache/sling/ide/filter/IgnoredResources.java
index 0ddf2ce1..e513a14a 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/filter/IgnoredResources.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/filter/IgnoredResources.java
@@ -20,6 +20,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.regex.Pattern;
 
+import org.apache.sling.ide.transport.RepositoryPath;
+
 /**
  * The <tt>IgnoredResources</tt> holds information about what resources are 
ignored in a local checkout
  */
@@ -55,9 +57,9 @@ public class IgnoredResources {
         patterns.add(Pattern.compile(reg.toString()));
     }
 
-    public boolean isIgnored(String repositoryPath) {
+    public boolean isIgnored(RepositoryPath repositoryPath) {
         for (Pattern pattern : patterns) {
-            if (pattern.matcher(repositoryPath).matches()) {
+            if (pattern.matcher(repositoryPath.asString()).matches()) {
                 return true;
             }
         }
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/serialization/SerializationManager.java
 
b/shared/api/src/main/java/org/apache/sling/ide/serialization/SerializationManager.java
index 6fa32fd9..27865ba4 100644
--- 
a/shared/api/src/main/java/org/apache/sling/ide/serialization/SerializationManager.java
+++ 
b/shared/api/src/main/java/org/apache/sling/ide/serialization/SerializationManager.java
@@ -23,6 +23,7 @@ import org.apache.sling.ide.sync.content.WorkspaceFile;
 import org.apache.sling.ide.sync.content.WorkspacePath;
 import org.apache.sling.ide.sync.content.WorkspaceResource;
 import org.apache.sling.ide.transport.Repository;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public interface SerializationManager {
@@ -52,7 +53,7 @@ public interface SerializationManager {
      * @param localPath the local path
      * @return the repository path
      */
-    String getRepositoryPath(WorkspacePath localPath);
+    RepositoryPath getRepositoryPath(WorkspacePath localPath);
 
     /**
      * Maps a repository name to a local name.
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/sync/content/WorkspacePath.java 
b/shared/api/src/main/java/org/apache/sling/ide/sync/content/WorkspacePath.java
index eeb450d8..51f95088 100644
--- 
a/shared/api/src/main/java/org/apache/sling/ide/sync/content/WorkspacePath.java
+++ 
b/shared/api/src/main/java/org/apache/sling/ide/sync/content/WorkspacePath.java
@@ -26,6 +26,7 @@ import org.apache.sling.ide.util.PathUtil;
  * 
  * <p>The workspace path always uses the forward slash ( <tt>/</tt> ) for 
separating segments.</p>
  *
+ * @see {@link PathUtil}
  */
 public class WorkspacePath {
 
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
 
b/shared/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
index 2f596e16..09cecfa9 100644
--- 
a/shared/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
+++ 
b/shared/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
@@ -38,9 +38,9 @@ import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.CommandContext;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryException;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceAndInfo;
 import org.apache.sling.ide.transport.ResourceProxy;
-import org.apache.sling.ide.util.PathUtil;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
@@ -73,7 +73,7 @@ public class DefaultSyncCommandFactory implements 
SyncCommandFactory {
         }
         
         WorkspacePath resourceLocalPath = 
resource.getPathRelativeToSyncDir().absolute();
-        String repositoryPath = resourceLocalPath.asPortableString();
+        RepositoryPath repositoryPath = 
serializationManager.getRepositoryPath(resourceLocalPath);
 
         FilterResult filterResult = 
resource.getProject().getFilter().filter(repositoryPath);
         
@@ -163,8 +163,8 @@ localFile);
                
                ResourceProxy serializationData = 
serializationManager.readSerializationData( possibleSerializationFile);
 
-               String repositoryPath = 
serializationManager.getRepositoryPath(resourceLocalPath);
-               String potentialPath = serializationData.getPath();
+               RepositoryPath repositoryPath = 
serializationManager.getRepositoryPath(resourceLocalPath);
+               RepositoryPath potentialPath = serializationData.getPath();
                boolean covered = serializationData.covers(repositoryPath);
 
                logger.trace(
@@ -360,7 +360,7 @@ localFile);
 
        while (childIterator.hasNext()) {
            ResourceProxy child = childIterator.next();
-           String childName = PathUtil.getName(child.getPath());
+           String childName = child.getPath().getName();
            String osChildName = serializationManager.getLocalName(childName);
 
            // covered children might have a FS representation, depending on 
their child nodes, so
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/transport/Command.java 
b/shared/api/src/main/java/org/apache/sling/ide/transport/Command.java
index 75671d5b..bb8634c5 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/transport/Command.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/transport/Command.java
@@ -32,7 +32,7 @@ public interface Command<T> {
 
        Result<T> execute();
 
-    String getPath();
+       RepositoryPath getPath();
 
     Set<CommandExecutionFlag> getFlags();
     
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/transport/Repository.java 
b/shared/api/src/main/java/org/apache/sling/ide/transport/Repository.java
index 62aadba9..4765ee3c 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/transport/Repository.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/transport/Repository.java
@@ -106,7 +106,7 @@ public interface Repository {
      */
     Command<Void> newReorderChildNodesCommand(ResourceProxy resourceProxy);
        
-    Command<Void> newDeleteNodeCommand(String path);
+    Command<Void> newDeleteNodeCommand(RepositoryPath path);
  
     /**
      * Retrieves information about the resource located at <tt>path</tt> and 
its direct descendants
@@ -114,7 +114,7 @@ public interface Repository {
      * @param path
      * @return a <tt>ResourceProxy</tt> rooted at <tt>path</tt> and its direct 
descendants
      */
-    Command<ResourceProxy> newListChildrenNodeCommand(String path);
+    Command<ResourceProxy> newListChildrenNodeCommand(RepositoryPath path);
        
     /**
      * Retrieves all properties of a resource located at <tt>path</tt>
@@ -122,9 +122,9 @@ public interface Repository {
      * @param path
      * @return all properties for the resource located at <tt>path</tt>
      */
-    Command<ResourceProxy> newGetNodeContentCommand(String path);
+    Command<ResourceProxy> newGetNodeContentCommand(RepositoryPath path);
 
-       Command<byte[]> newGetNodeCommand(String path);
+       Command<byte[]> newGetNodeCommand(RepositoryPath path);
        
        /**
         * Returns the node type registry - when the underlying server is 
started -
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/transport/RepositoryPath.java 
b/shared/api/src/main/java/org/apache/sling/ide/transport/RepositoryPath.java
new file mode 100644
index 00000000..a0e4e8a9
--- /dev/null
+++ 
b/shared/api/src/main/java/org/apache/sling/ide/transport/RepositoryPath.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.ide.transport;
+
+import java.util.Objects;
+
+import org.apache.sling.ide.util.PathUtil;
+
+/**
+ * A path in the remote repository
+ * 
+ * <p>The repository path always uses the forward slash ( <tt>/</tt> ) for 
separating segments.</p>
+ * 
+ * @see {@link PathUtil}
+ */
+public class RepositoryPath {
+    
+    private final String path;
+
+    public RepositoryPath(String path) {
+        // validate it is not null or empty and starts with a slash
+        if (path == null || path.isEmpty() || !path.startsWith("/"))
+            throw new IllegalArgumentException("Invalid repository path: " + 
path);
+        
+        // TODO - more validations
+        this.path = path;
+    }
+    
+    public boolean isParent(RepositoryPath maybeChild) {
+        return PathUtil.isParent(asString(), maybeChild.asString());
+    }
+
+    public boolean isAncestor(RepositoryPath other) {
+        return PathUtil.isAncestor(asString(), other.asString());
+    }    
+    
+    public boolean isDescendent(RepositoryPath other) {
+        return PathUtil.isDescendent(asString(), other.asString());
+    }
+    
+    public String getName() {
+        return PathUtil.getName(path);
+    }
+    
+    public RepositoryPath getParent() {
+        return new RepositoryPath(PathUtil.getParent(asString()));
+    }
+    
+    public RepositoryPath addChild(String name) {
+        return new RepositoryPath(PathUtil.join(path, name));
+    }
+    
+    public String asString() {
+        return path;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(path);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        RepositoryPath other = (RepositoryPath) obj;
+        return Objects.equals(path, other.path);
+    }
+
+    @Override
+    public String toString() {
+        return "RepositoryPath [path=" + path + "]";
+    }
+}
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/transport/ResourceProxy.java 
b/shared/api/src/main/java/org/apache/sling/ide/transport/ResourceProxy.java
index ccbd5a40..483e266d 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/transport/ResourceProxy.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/transport/ResourceProxy.java
@@ -42,25 +42,23 @@ import java.util.Map;
  */
 public class ResourceProxy {
 
-    private final String path;
+    private final RepositoryPath path;
     private final Map<String, Object> properties;
     private final List<ResourceProxy> children = new ArrayList<>();
     private final Map<Class<?>, Object> adapted = new HashMap<>(1);
 
-    // TODO - use a typed path object?
-    public ResourceProxy(String path) {
-        this(path, new HashMap<String, Object>());
+    public ResourceProxy(RepositoryPath path) {
+        this(path, new HashMap<>());
     }
 
-    public ResourceProxy(String path, Map<String, Object> properties) {
+    public ResourceProxy(RepositoryPath path, Map<String, Object> properties) {
         this.path = path;
         this.properties = properties;
     }
 
     public void addChild(ResourceProxy child) {
 
-        // TODO - should validate for direct parent
-        if (!isParent(path, child.getPath())) {
+        if ( !path.isParent(child.path) ) {
             throw new IllegalArgumentException("Resource at path " + 
child.getPath() + " is not a direct child of "
                     + path);
         }
@@ -73,7 +71,7 @@ public class ResourceProxy {
         this.properties.put(name, value);
     }
 
-    public String getPath() {
+    public RepositoryPath getPath() {
         return path;
     }
 
@@ -113,11 +111,11 @@ public class ResourceProxy {
         return coveredChildren;
     }
 
-    public boolean covers(String path) {
+    public boolean covers(RepositoryPath path) {
         for (ResourceProxy child : getCoveredChildren()) {
             if (child.getPath().equals(path)) {
                 return true;
-            } else if (isDescendent(child.getPath(), path)) {
+            } else if (child.getPath().isDescendent(path)) {
                 return child.covers(path);
             }
         }
@@ -125,35 +123,11 @@ public class ResourceProxy {
         return false;
     }
 
-    private boolean isParent(String parentPath, String childPath) {
-
-        if (!isDescendent(parentPath, childPath)) {
-            return false;
-        }
-
-        for (int i = parentPath.length() + 1; i < childPath.length(); i++) {
-            if (childPath.charAt(i) == '/') {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private boolean isDescendent(String parentPath, String childPath) {
-        if (parentPath.equals("/")) {
-            return childPath.length() > 1;
-        }
-
-        return parentPath.length() < childPath.length() && 
childPath.charAt(parentPath.length()) == '/'
-                    && childPath.startsWith(parentPath);
-    }
-
-    public ResourceProxy getChild(String path) {
+    public ResourceProxy getChild(RepositoryPath path) {
         for (ResourceProxy child : getChildren()) {
             if (child.getPath().equals(path)) {
                 return child;
-            } else if (isDescendent(child.getPath(), path)) {
+            } else if ( child.getPath().isDescendent(path) ) {
                 return child.getChild(path);
             }
         }
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/transport/impl/DefaultBatcher.java
 
b/shared/api/src/main/java/org/apache/sling/ide/transport/impl/DefaultBatcher.java
index 62348fa9..c466e913 100644
--- 
a/shared/api/src/main/java/org/apache/sling/ide/transport/impl/DefaultBatcher.java
+++ 
b/shared/api/src/main/java/org/apache/sling/ide/transport/impl/DefaultBatcher.java
@@ -22,7 +22,7 @@ import java.util.ListIterator;
 
 import org.apache.sling.ide.transport.Batcher;
 import org.apache.sling.ide.transport.Command;
-import org.apache.sling.ide.util.PathUtil;
+import org.apache.sling.ide.transport.RepositoryPath;
 
 public class DefaultBatcher implements Batcher {
     
@@ -93,17 +93,17 @@ public class DefaultBatcher implements Batcher {
         }
 
         private void processDelete(Command<?> newCmd) {
-            String path = newCmd.getPath();
+            RepositoryPath path = newCmd.getPath();
             for ( ListIterator<Command<?>> iterator = deletes.listIterator(); 
iterator.hasNext(); ) {
                 
                 // if we already have an ancestor deleted, skip this one
                 Command<?> oldCmd = iterator.next();
-                if ( PathUtil.isAncestor(oldCmd.getPath(), path ) ) {
+                if ( oldCmd.getPath().isAncestor(path) ) {
                     return;
                 }
                 
                 // if we are delete an ancestor of another resource which gets 
deleted, replace it
-                if ( PathUtil.isAncestor(path, oldCmd.getPath())) {
+                if ( path.isAncestor(oldCmd.getPath())) {
                     iterator.set(newCmd);
                     return;
                 }
@@ -114,7 +114,7 @@ public class DefaultBatcher implements Batcher {
         }
         
         private void processWithPathEqualityCheck(Command<?> newCmd, 
List<Command<?>> oldCmds) {
-            String path = newCmd.getPath();
+            RepositoryPath path = newCmd.getPath();
             for (Command<?> oldCmd : oldCmds) {
                 // if we already have an add-or-update for this path, skip it  
  
                 if ( path.equals(oldCmd.getPath()) ) {
diff --git a/shared/api/src/main/java/org/apache/sling/ide/util/PathUtil.java 
b/shared/api/src/main/java/org/apache/sling/ide/util/PathUtil.java
index 6f146ab2..282cf7d2 100644
--- a/shared/api/src/main/java/org/apache/sling/ide/util/PathUtil.java
+++ b/shared/api/src/main/java/org/apache/sling/ide/util/PathUtil.java
@@ -16,6 +16,17 @@
  */
 package org.apache.sling.ide.util;
 
+import org.apache.sling.ide.serialization.SerializationManager;
+import org.apache.sling.ide.sync.content.WorkspacePath;
+import org.apache.sling.ide.transport.RepositoryPath;
+
+/**
+ * Utility class that provides implementations useful for both {@link 
WorkspacePath} and {@link RepositoryPath}
+ * 
+ * <p><strong>NOTE:</strong> The two path implementations are intentionally 
kept separate to avoid confusion about
+ * which kind of path is being used. Conversions must be done via {@link 
SerializationManager#getRepositoryPath(WorkspacePath)}
+ * and not fall back on the String form of the paths.</p>
+ */
 public class PathUtil {
 
     public static String join(String first, String second) {
@@ -70,4 +81,33 @@ public class PathUtil {
         
         return false;
     }
+    
+    public static boolean isParent(String parentPath, String childPath) {
+
+        if (!isDescendent(parentPath, childPath)) {
+            return false;
+        }
+
+        for (int i = parentPath.length() + 1; i < childPath.length(); i++) {
+            if (childPath.charAt(i) == '/') {
+                return false;
+            }
+        }
+
+        return true;
+    }
+    
+    public static boolean isDescendent(String parentPath, String childPath) {
+        
+        if (parentPath.equals("/")) {
+            return childPath.length() > 1;
+        }
+
+        return parentPath.length() < childPath.length() && 
childPath.charAt(parentPath.length()) == '/'
+                    && childPath.startsWith(parentPath);
+    }
+    
+    private PathUtil() {
+        
+    }
 }
diff --git 
a/shared/api/src/main/java/org/apache/sling/ide/util/package-info.java 
b/shared/api/src/main/java/org/apache/sling/ide/util/package-info.java
deleted file mode 100644
index 13a75c0e..00000000
--- a/shared/api/src/main/java/org/apache/sling/ide/util/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
[email protected]("1.2.0")
-package org.apache.sling.ide.util;
\ No newline at end of file
diff --git 
a/shared/api/src/test/java/org/apache/sling/ide/filter/IgnoredResourcesTest.java
 
b/shared/api/src/test/java/org/apache/sling/ide/filter/IgnoredResourcesTest.java
index a4f21ec1..d9f4a7a2 100644
--- 
a/shared/api/src/test/java/org/apache/sling/ide/filter/IgnoredResourcesTest.java
+++ 
b/shared/api/src/test/java/org/apache/sling/ide/filter/IgnoredResourcesTest.java
@@ -19,6 +19,7 @@ package org.apache.sling.ide.filter;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertThat;
 
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.junit.Test;
 
 public class IgnoredResourcesTest {
@@ -29,7 +30,7 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/content", "en");
 
-        assertThat(r.isIgnored("/content/en"), equalTo(true));
+        assertThat(r.isIgnored(new RepositoryPath("/content/en")), 
equalTo(true));
     }
 
     @Test
@@ -38,8 +39,8 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/content", "*sync");
 
-        assertThat(r.isIgnored("/content/contentsync"), equalTo(true));
-        assertThat(r.isIgnored("/content/content"), equalTo(false));
+        assertThat(r.isIgnored(new RepositoryPath("/content/contentsync")), 
equalTo(true));
+        assertThat(r.isIgnored(new RepositoryPath("/content/content")), 
equalTo(false));
     }
 
     @Test
@@ -48,7 +49,7 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/content", "#en");
 
-        assertThat(r.isIgnored("/content/#en"), equalTo(false));
+        assertThat(r.isIgnored(new RepositoryPath("/content/#en")), 
equalTo(false));
     }
 
     @Test
@@ -57,8 +58,8 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/content", "en.html");
 
-        assertThat(r.isIgnored("/content/en.html"), equalTo(true));
-        assertThat(r.isIgnored("/content/en-html"), equalTo(false));
+        assertThat(r.isIgnored(new RepositoryPath("/content/en.html")), 
equalTo(true));
+        assertThat(r.isIgnored(new RepositoryPath("/content/en-html")), 
equalTo(false));
     }
 
     @Test
@@ -67,7 +68,7 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/content", "?en");
 
-        assertThat(r.isIgnored("/content/zen"), equalTo(true));
+        assertThat(r.isIgnored(new RepositoryPath("/content/zen")), 
equalTo(true));
     }
 
     @Test
@@ -76,7 +77,7 @@ public class IgnoredResourcesTest {
         IgnoredResources r = new IgnoredResources();
         r.registerRegExpIgnoreRule("/", "en");
 
-        assertThat(r.isIgnored("/en"), equalTo(true));
+        assertThat(r.isIgnored(new RepositoryPath("/en")), equalTo(true));
 
     }
 }
diff --git 
a/shared/api/src/test/java/org/apache/sling/ide/serialization/NodeTypeResourceBuilder.java
 
b/shared/api/src/test/java/org/apache/sling/ide/serialization/NodeTypeResourceBuilder.java
index c39d4bb1..cd58a4c4 100644
--- 
a/shared/api/src/test/java/org/apache/sling/ide/serialization/NodeTypeResourceBuilder.java
+++ 
b/shared/api/src/test/java/org/apache/sling/ide/serialization/NodeTypeResourceBuilder.java
@@ -16,19 +16,14 @@
  */
 package org.apache.sling.ide.serialization;
 
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class NodeTypeResourceBuilder {
 
     public static NodeTypeResourceBuilder newBuilder(ResourceProxy parent, 
String name) {
 
-        String path;
-
-        if (parent.getPath().endsWith("/")) {
-            path = parent.getPath() + name;
-        } else {
-            path = parent.getPath() + "/" + name;
-        }
+        RepositoryPath path = parent.getPath().addChild(name);
 
         ResourceProxy resourceProxy = new ResourceProxy(path);
         // set defaults
diff --git 
a/shared/api/src/test/java/org/apache/sling/ide/serialization/StubRepository.java
 
b/shared/api/src/test/java/org/apache/sling/ide/serialization/StubRepository.java
index bd6ae3db..e51a93a5 100644
--- 
a/shared/api/src/test/java/org/apache/sling/ide/serialization/StubRepository.java
+++ 
b/shared/api/src/test/java/org/apache/sling/ide/serialization/StubRepository.java
@@ -23,27 +23,28 @@ import 
org.apache.sling.ide.transport.FallbackNodeTypeRegistry;
 import org.apache.sling.ide.transport.NodeTypeRegistry;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryInfo;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class StubRepository implements Repository {
 
     @Override
-    public Command<ResourceProxy> newListChildrenNodeCommand(final String 
path) {
+    public Command<ResourceProxy> newListChildrenNodeCommand(final 
RepositoryPath path) {
         return null;
     }
 
     @Override
-    public Command<ResourceProxy> newGetNodeContentCommand(String path) {
+    public Command<ResourceProxy> newGetNodeContentCommand(RepositoryPath 
path) {
         return null;
     }
 
     @Override
-    public Command<byte[]> newGetNodeCommand(String path) {
+    public Command<byte[]> newGetNodeCommand(RepositoryPath path) {
         return null;
     }
 
     @Override
-    public Command<Void> newDeleteNodeCommand(String path) {
+    public Command<Void> newDeleteNodeCommand(RepositoryPath path) {
         return null;
     }
 
diff --git 
a/shared/api/src/test/java/org/apache/sling/ide/transport/ResourceProxyTest.java
 
b/shared/api/src/test/java/org/apache/sling/ide/transport/ResourceProxyTest.java
index 5e373c9e..2e888aa6 100644
--- 
a/shared/api/src/test/java/org/apache/sling/ide/transport/ResourceProxyTest.java
+++ 
b/shared/api/src/test/java/org/apache/sling/ide/transport/ResourceProxyTest.java
@@ -23,32 +23,34 @@ import static org.junit.Assert.assertThat;
 import org.junit.Test;
 
 public class ResourceProxyTest {
+    
+    private static final RepositoryPath PATH_CONTENT = new 
RepositoryPath("/content"); 
 
     @Test
     public void coveredChildren_firstLevel() {
 
-        ResourceProxy r = new ResourceProxy("/content");
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
         r.addChild(newResource("/content/test", "nt:unstructured"));
 
-        assertThat(r.covers("/content/test"), is(true));
+        assertThat(r.covers(new RepositoryPath("/content/test")), is(true));
     }
 
     @Test
     public void coveredChildren_secondLevel() {
 
-        ResourceProxy r = new ResourceProxy("/content");
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
         ResourceProxy child = newResource("/content/test", "nt:unstructured");
         r.addChild(child);
 
         child.addChild(newResource("/content/test/en", "nt:unstructured"));
 
-        assertThat(r.covers("/content/test/en"), is(true));
+        assertThat(r.covers(new RepositoryPath("/content/test/en")), is(true));
     }
 
     @Test
     public void coveredChildren_thirdLevel() {
 
-        ResourceProxy r = new ResourceProxy("/content");
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
 
         ResourceProxy child = newResource("/content/test", "nt:unstructured");
         r.addChild(child);
@@ -58,34 +60,34 @@ public class ResourceProxyTest {
 
         grandChild.addChild(newResource("/content/test/en/welcome", 
"nt:unstructured"));
 
-        assertThat(r.covers("/content/test/en/welcome"), is(true));
+        assertThat(r.covers(new RepositoryPath("/content/test/en/welcome")), 
is(true));
     }
 
     @Test
     public void coveredChildren_notCoveredFirstLevel() {
 
-        ResourceProxy r = new ResourceProxy("/content");
-        r.addChild(new ResourceProxy("/content/test"));
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
+        r.addChild(new ResourceProxy(PATH_CONTENT.addChild("test")));
 
-        assertThat(r.covers("/content/test"), is(false));
+        assertThat(r.covers(new RepositoryPath("/content/test")), is(false));
     }
 
     @Test
     public void coveredChildren_notCoveredSecondLevel() {
 
-        ResourceProxy r = new ResourceProxy("/content");
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
         ResourceProxy child = newResource("/content/test", "nt:unstructured");
         r.addChild(child);
 
-        child.addChild(new ResourceProxy("/content/test/en"));
+        child.addChild(new 
ResourceProxy(PATH_CONTENT.addChild("test").addChild("en")));
 
-        assertThat(r.covers("/content/test/en"), is(false));
+        assertThat(r.covers(new RepositoryPath("/content/test/en")), 
is(false));
     }
 
     @Test
     public void getChild() {
 
-        ResourceProxy r = new ResourceProxy("/content");
+        ResourceProxy r = new ResourceProxy(PATH_CONTENT);
         ResourceProxy child = newResource("/content/test", "nt:unstructured");
         r.addChild(child);
 
@@ -95,15 +97,15 @@ public class ResourceProxyTest {
         ResourceProxy grandGrandChild = 
newResource("/content/test/en/welcome", "nt:unstructured");
         grandChild.addChild(grandGrandChild);
 
-        assertThat(r.getChild("/content/test"), is(child));
-        assertThat(r.getChild("/content/test/en"), is(grandChild));
-        assertThat(r.getChild("/content/test/en/welcome"), 
is(grandGrandChild));
-        assertThat(r.getChild("/content/test/en2"), is(nullValue()));
+        assertThat(r.getChild(new RepositoryPath("/content/test")), is(child));
+        assertThat(r.getChild(new RepositoryPath("/content/test/en")), 
is(grandChild));
+        assertThat(r.getChild(new RepositoryPath("/content/test/en/welcome")), 
is(grandGrandChild));
+        assertThat(r.getChild(new RepositoryPath("/content/test/en2")), 
is(nullValue()));
     }
 
     private ResourceProxy newResource(String path, String primaryType) {
 
-        ResourceProxy child = new ResourceProxy(path);
+        ResourceProxy child = new ResourceProxy(new RepositoryPath(path));
         child.addProperty("jcr:primaryType", primaryType);
         return child;
     }
@@ -111,25 +113,25 @@ public class ResourceProxyTest {
     @Test(expected = IllegalArgumentException.class)
     public void addChild_IllegalChildRejected() {
 
-        new ResourceProxy("/content").addChild(new ResourceProxy("/var"));
+        new ResourceProxy(new RepositoryPath("/content")).addChild(new 
ResourceProxy(new RepositoryPath("/var")));  
     }
 
     @Test
     public void addChild_childOfRootNode() {
 
-        new ResourceProxy("/").addChild(new ResourceProxy("/var"));
+        new ResourceProxy(new RepositoryPath("/")).addChild(new 
ResourceProxy(new RepositoryPath("/var")));
     }
 
     @Test
     public void addChild_childOfRegularNode() {
 
-        new ResourceProxy("/content").addChild(new 
ResourceProxy("/content/test"));
+        new ResourceProxy(new RepositoryPath("/content")).addChild(new 
ResourceProxy(new RepositoryPath("/content/test")));
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void addChild_deeplyNested() {
 
-        new ResourceProxy("/content").addChild(new 
ResourceProxy("/content/test/en"));
+        new ResourceProxy(new RepositoryPath("/content")).addChild(new 
ResourceProxy(new RepositoryPath("/content/test/en")));
     }
 
 }
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommand.java
index 803491c1..19914516 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommand.java
@@ -52,15 +52,14 @@ import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 
-import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.util.JcrConstants;
 import org.apache.sling.ide.filter.FilterResult;
 import org.apache.sling.ide.log.Logger;
 import org.apache.sling.ide.sync.content.WorkspaceFile;
 import org.apache.sling.ide.transport.CommandContext;
 import org.apache.sling.ide.transport.Repository.CommandExecutionFlag;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
-import org.apache.sling.ide.util.PathUtil;
 
 public class AddOrUpdateNodeCommand extends JcrCommand<Void> {
 
@@ -87,7 +86,7 @@ public class AddOrUpdateNodeCommand extends JcrCommand<Void> {
 
     private void update(ResourceProxy resource, Session session) throws 
RepositoryException, IOException {
 
-        String path = resource.getPath();
+        String path = resource.getPath().asString();
         boolean nodeExists = session.nodeExists(path);
 
         Node node;
@@ -100,7 +99,7 @@ public class AddOrUpdateNodeCommand extends JcrCommand<Void> 
{
                    node = createNode(resource, session);
                    getLogger().trace("Created node at {0} with primaryType 
{1}", path, node.getPrimaryNodeType().getName());
                } catch (RepositoryException e) {
-                       throw new RepositoryException("Could not create node at 
" + Text.getRelativeParent(resource.getPath(), 1) + " based on resource " + 
resource, e);
+                       throw new RepositoryException("Could not create node at 
" + resource.getPath().getParent().asString() + " based on resource " + 
resource, e);
                }
         }
 
@@ -128,7 +127,7 @@ public class AddOrUpdateNodeCommand extends 
JcrCommand<Void> {
             return;
         }
         
-        Map<String, ResourceProxy> resourceChildrenPaths = new 
HashMap<>(resourceChildren.size());
+        Map<RepositoryPath, ResourceProxy> resourceChildrenPaths = new 
HashMap<>(resourceChildren.size());
         for (ResourceProxy child : resourceChildren) {
             resourceChildrenPaths.put(child.getPath(), child);
         }
@@ -136,18 +135,19 @@ public class AddOrUpdateNodeCommand extends 
JcrCommand<Void> {
         for (NodeIterator it = node.getNodes(); it.hasNext();) {
 
             Node child = it.nextNode();
-
-            if (resourceChildrenPaths.containsKey(child.getPath())) {
+            RepositoryPath childRepositoryPath = new 
RepositoryPath(child.getPath());
+            
+            if (resourceChildrenPaths.containsKey(childRepositoryPath)) {
                 // only descend for reordering when the child node is covered 
; otherwise we
                 // don't have enough information
-                if (resource2.covers(child.getPath())) {
-                    processDeletedNodes(child, 
resourceChildrenPaths.get(child.getPath()));
+                if (resource2.covers(childRepositoryPath)) {
+                    processDeletedNodes(child, 
resourceChildrenPaths.get(childRepositoryPath));
                 }
                 continue;
             }
 
             if ( context.filter() != null 
-                    && context.filter(). filter(child.getPath()) == 
FilterResult.DENY ) {
+                    && context.filter(). filter(new 
RepositoryPath(child.getPath())) == FilterResult.DENY ) {
                 getLogger().trace("Not deleting node at {0} since it is not 
included in the filter", child.getPath());
                 continue;
             }
@@ -160,7 +160,7 @@ public class AddOrUpdateNodeCommand extends 
JcrCommand<Void> {
 
     private Node createNode(ResourceProxy resource, Session session) throws 
RepositoryException, FileNotFoundException {
 
-        String parentLocation = Text.getRelativeParent(resource.getPath(), 1);
+        String parentLocation = resource.getPath().getParent().asString();
         if (parentLocation.isEmpty()) {
             parentLocation = "/";
         }
@@ -172,7 +172,7 @@ public class AddOrUpdateNodeCommand extends 
JcrCommand<Void> {
 
         String primaryType = (String) 
resource.getProperties().get(JCR_PRIMARYTYPE);
         Node parent = session.getNode(parentLocation);
-        String childName = PathUtil.getName(resource.getPath());
+        String childName = resource.getPath().getName();
         if (primaryType == null) {
             return parent.addNode(childName);
         } else {
@@ -182,7 +182,7 @@ public class AddOrUpdateNodeCommand extends 
JcrCommand<Void> {
 
     private void updateNode(Node node, ResourceProxy resource) throws 
RepositoryException, IOException {
 
-        if (node.getPath().equals(getPath()) && fileInfo != null) {
+        if (new RepositoryPath(node.getPath()).equals(getPath()) && fileInfo 
!= null) {
             updateFileLikeNodeTypes(node);
         }
 
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/DeleteNodeCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/DeleteNodeCommand.java
index f430fea6..4d4d44c2 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/DeleteNodeCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/DeleteNodeCommand.java
@@ -24,18 +24,19 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 
 public class DeleteNodeCommand extends JcrCommand<Void> {
 
-    public DeleteNodeCommand(Repository repository, Credentials credentials, 
String path, Logger logger) {
+    public DeleteNodeCommand(Repository repository, Credentials credentials, 
RepositoryPath path, Logger logger) {
         super(repository, credentials, path, logger);
     }
 
     @Override
     protected Void execute0(Session session) throws RepositoryException, 
IOException {
 
-        if (session.nodeExists(getPath())) {
-            session.getNode(getPath()).remove();
+        if (session.nodeExists(getPath().asString())) {
+            session.getNode(getPath().asString()).remove();
         }
 
         return null;
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeCommand.java
index d5878334..fe43b468 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeCommand.java
@@ -30,17 +30,18 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 
 public class GetNodeCommand extends JcrCommand<byte[]> {
     
-    public GetNodeCommand(Repository repository, Credentials credentials, 
String path, Logger logger) {
+    public GetNodeCommand(Repository repository, Credentials credentials, 
RepositoryPath path, Logger logger) {
         super(repository, credentials, path, logger);
     }
 
     @Override
     protected byte[] execute0(Session session) throws RepositoryException, 
IOException {
 
-        Node node = session.getNode(getPath());
+        Node node = session.getNode(getPath().asString());
 
         Property property;
         if (node.hasProperty("jcr:data")) {
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeContentCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeContentCommand.java
index b505822a..c591b124 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeContentCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/GetNodeContentCommand.java
@@ -23,18 +23,19 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class GetNodeContentCommand extends JcrCommand<ResourceProxy> {
 
-    public GetNodeContentCommand(Repository repository, Credentials 
credentials, String path, Logger logger) {
+    public GetNodeContentCommand(Repository repository, Credentials 
credentials, RepositoryPath path, Logger logger) {
         super(repository, credentials, path, logger);
     }
 
     @Override
     protected ResourceProxy execute0(Session session) throws 
RepositoryException {
 
-        Node node = session.getNode(getPath());
+        Node node = session.getNode(getPath().asString());
 
         return nodeToResource(node);
     }
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/JcrCommand.java 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/JcrCommand.java
index 9b0ecf83..04b9a7dc 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/JcrCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/JcrCommand.java
@@ -36,6 +36,7 @@ import javax.jcr.Session;
 import org.apache.sling.ide.log.Logger;
 import org.apache.sling.ide.transport.Command;
 import org.apache.sling.ide.transport.Repository.CommandExecutionFlag;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.Result;
 
@@ -43,11 +44,11 @@ public abstract class JcrCommand<T> implements Command<T> {
 
     private final Credentials credentials;
     private final Repository repository;
-    private final String path;
+    private final RepositoryPath path;
     private final Logger logger;
     private final EnumSet<CommandExecutionFlag> flags;
 
-    public JcrCommand(Repository repository, Credentials credentials, String 
path, Logger logger,
+    public JcrCommand(Repository repository, Credentials credentials, 
RepositoryPath path, Logger logger,
             CommandExecutionFlag... flags) {
 
         this.repository = repository;
@@ -84,7 +85,8 @@ public abstract class JcrCommand<T> implements Command<T> {
 
     protected abstract T execute0(Session session) throws RepositoryException, 
IOException;
 
-    public String getPath() {
+    @Override
+    public RepositoryPath getPath() {
         return path;
     }
 
@@ -92,6 +94,7 @@ public abstract class JcrCommand<T> implements Command<T> {
         return logger;
     }
 
+    @Override
     public Set<CommandExecutionFlag> getFlags() {
         return Collections.unmodifiableSet(flags);
     }
@@ -103,7 +106,7 @@ public abstract class JcrCommand<T> implements Command<T> {
 
     protected ResourceProxy nodeToResource(Node node) throws 
RepositoryException {
     
-        ResourceProxy resource = new ResourceProxy(node.getPath());
+        ResourceProxy resource = new ResourceProxy(new 
RepositoryPath(node.getPath()));
         resource.addAdapted(Node.class, node);
 
         PropertyIterator properties = node.getProperties();
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListChildrenCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListChildrenCommand.java
index 1a87cea2..7635d914 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListChildrenCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListChildrenCommand.java
@@ -24,18 +24,19 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class ListChildrenCommand extends JcrCommand<ResourceProxy> {
 
-    public ListChildrenCommand(Repository repository, Credentials credentials, 
String path, Logger logger) {
+    public ListChildrenCommand(Repository repository, Credentials credentials, 
RepositoryPath path, Logger logger) {
         super(repository, credentials, path, logger);
     }
 
     @Override
     protected ResourceProxy execute0(Session session) throws 
RepositoryException {
 
-        Node node = session.getNode(getPath());
+        Node node = session.getNode(getPath().asString());
         NodeIterator nodes = node.getNodes();
 
         ResourceProxy parent = nodeToResource(node);
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListTreeCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListTreeCommand.java
index 16549073..dc2b016c 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListTreeCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ListTreeCommand.java
@@ -24,13 +24,14 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class ListTreeCommand extends JcrCommand<ResourceProxy> {
 
     private final int levels;
 
-    public ListTreeCommand(Repository repository, Credentials credentials, 
String path, int levels, Logger logger) {
+    public ListTreeCommand(Repository repository, Credentials credentials, 
RepositoryPath path, int levels, Logger logger) {
         super(repository, credentials, path, logger);
         this.levels = Math.max(1,levels);
     }
@@ -38,7 +39,7 @@ public class ListTreeCommand extends 
JcrCommand<ResourceProxy> {
     @Override
     protected ResourceProxy execute0(Session session) throws 
RepositoryException {
 
-        Node node = session.getNode(getPath());
+        Node node = session.getNode(getPath().asString());
 
         ResourceProxy parent = nodeToResource(node);
 
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommand.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommand.java
index 48460f6e..a2c8dd6a 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommand.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommand.java
@@ -31,7 +31,6 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 
-import org.apache.jackrabbit.util.Text;
 import org.apache.sling.ide.log.Logger;
 import org.apache.sling.ide.transport.ResourceProxy;
 
@@ -53,12 +52,12 @@ public class ReorderChildNodesCommand extends 
JcrCommand<Void> {
     @Override
     protected Void execute0(Session session) throws RepositoryException, 
IOException {
 
-        boolean nodeExists = session.nodeExists(getPath());
+        boolean nodeExists = session.nodeExists(getPath().asString());
         if (!nodeExists) {
             return null;
         }
 
-        Node node = session.getNode(getPath());
+        Node node = session.getNode(getPath().asString());
 
         NodeType primaryNodeType = node.getPrimaryNodeType();
 
@@ -93,7 +92,7 @@ public class ReorderChildNodesCommand extends 
JcrCommand<Void> {
         }
 
         for (ResourceProxy childResources : children) {
-            resourceChildNames.add(Text.getName(childResources.getPath()));
+            resourceChildNames.add(childResources.getPath().getName());
         }
         ListIterator<Node> nodeChildrenListIt = nodeChildren.listIterator();
 
@@ -116,7 +115,7 @@ public class ReorderChildNodesCommand extends 
JcrCommand<Void> {
             Node childNode = nodeChildrenListIt.next();
 
             // order is as expected, skip reordering
-            if 
(Text.getName(childResource.getPath()).equals(childNode.getName())) {
+            if (childResource.getPath().getName().equals(childNode.getName())) 
{
                 // descend into covered child resources once they are properly 
arranged and perform reordering
                 if (resourceToReorder.covers(childResource.getPath())) {
                     reorderChildNodes(childNode, childResource);
@@ -133,16 +132,16 @@ public class ReorderChildNodesCommand extends 
JcrCommand<Void> {
 
             String expectedParentName;
             if (childrenIterator.hasNext()) {
-                expectedParentName = 
Text.getName(childrenIterator.next().getPath());
+                expectedParentName = 
childrenIterator.next().getPath().getName();
                 childrenIterator.previous(); // move back
             } else {
                 expectedParentName = null;
             }
 
             getLogger().trace("For node at {0} ordering {1} before {2}", 
nodeToReorder.getPath(),
-                    Text.getName(childResource.getPath()), expectedParentName);
+                    childResource.getPath().getName(), expectedParentName);
 
-            nodeToReorder.orderBefore(Text.getName(childResource.getPath()), 
expectedParentName);
+            nodeToReorder.orderBefore(childResource.getPath().getName(), 
expectedParentName);
         }
     }
 
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltNodeTypeFactory.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltNodeTypeFactory.java
index fc7d5163..3c95d9cd 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltNodeTypeFactory.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltNodeTypeFactory.java
@@ -28,9 +28,9 @@ import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.PropertyDefinition;
 
 import org.apache.sling.ide.transport.RepositoryException;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.Result;
-import org.apache.sling.ide.util.PathUtil;
 
 public class VltNodeTypeFactory {
 
@@ -45,7 +45,7 @@ public class VltNodeTypeFactory {
     }
 
     void init(VltRepository repository) throws RepositoryException {
-        Result<ResourceProxy> jcrSystem = 
repository.newListTreeNodeCommand("/jcr:system/jcr:nodeTypes", 3).execute();
+        Result<ResourceProxy> jcrSystem = 
repository.newListTreeNodeCommand(new 
RepositoryPath("/jcr:system/jcr:nodeTypes"), 3).execute();
         // phase 1: create all node types
         for (ResourceProxy child : jcrSystem.get().getChildren()) {
             
@@ -95,7 +95,7 @@ public class VltNodeTypeFactory {
 
         Set<VltNodeDefinition> nds = new HashSet<>();
         for (ResourceProxy ntChild : child.getChildren()) {
-            String ntChildName = PathUtil.getName(ntChild.getPath());
+            String ntChildName = ntChild.getPath().getName();
             if (ntChildName.startsWith("jcr:childNodeDefinition")) {
                 VltNodeDefinition nd = handleChildNodeDefinition(ntChild);
                 nds.add(nd);
@@ -112,7 +112,7 @@ public class VltNodeTypeFactory {
 
     private VltNodeType createNodeType(ResourceProxy child) {
         final VltNodeType nt = new VltNodeType(child);
-        final String name = PathUtil.getName(child.getPath());
+        final String name = child.getPath().getName();
         nt.setName(name);
         return nt;
     }
@@ -122,7 +122,7 @@ public class VltNodeTypeFactory {
         
         // load propertyDefinition children
         for (ResourceProxy aChild : child.getChildren()) {
-            String childName = PathUtil.getName(aChild.getPath());
+            String childName = aChild.getPath().getName();
             if (childName.startsWith("jcr:propertyDefinition")) {
                 String jcrName = 
(String)aChild.getProperties().get("jcr:name");
                 if (jcrName!=null) {
@@ -305,7 +305,7 @@ public class VltNodeTypeFactory {
             VltNodeType superType = (VltNodeType) declaredSupertypes[i];
             allSuperTypes.add(superType);
             nt.addSuperType(superType);
-            initSuperTypes(allSuperTypes, (VltNodeType) superType);
+            initSuperTypes(allSuperTypes, superType);
         }
     }
 
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepository.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepository.java
index 817c5b3d..7ed83a57 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepository.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepository.java
@@ -27,6 +27,7 @@ import org.apache.sling.ide.transport.CommandContext;
 import org.apache.sling.ide.transport.NodeTypeRegistry;
 import org.apache.sling.ide.transport.Repository;
 import org.apache.sling.ide.transport.RepositoryInfo;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 /**
@@ -93,26 +94,26 @@ public class VltRepository implements Repository {
     }
 
     @Override
-    public Command<Void> newDeleteNodeCommand(String path) {
+    public Command<Void> newDeleteNodeCommand(RepositoryPath path) {
         return new DeleteNodeCommand(jcrRepo, credentials, path, logger);
     }
 
     @Override
-    public Command<ResourceProxy> newListChildrenNodeCommand(String path) {
+    public Command<ResourceProxy> newListChildrenNodeCommand(RepositoryPath 
path) {
         return new ListChildrenCommand(jcrRepo, credentials, path, logger);
     }
 
     @Override
-    public Command<ResourceProxy> newGetNodeContentCommand(String path) {
+    public Command<ResourceProxy> newGetNodeContentCommand(RepositoryPath 
path) {
         return new GetNodeContentCommand(jcrRepo, credentials, path, logger);
     }
 
     @Override
-    public Command<byte[]> newGetNodeCommand(String path) {
+    public Command<byte[]> newGetNodeCommand(RepositoryPath path) {
        return new GetNodeCommand(jcrRepo, credentials, path, logger);
     }
 
-    Command<ResourceProxy> newListTreeNodeCommand(String path, int levels) {
+    Command<ResourceProxy> newListTreeNodeCommand(RepositoryPath path, int 
levels) {
         return new ListTreeCommand(jcrRepo, credentials, path, levels, logger);
     }
     
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/filter/VltFilter.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/filter/VltFilter.java
index 848ee8ac..3a280fc8 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/filter/VltFilter.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/filter/VltFilter.java
@@ -25,6 +25,7 @@ import 
org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.impl.AggregateManagerImpl;
 import org.apache.sling.ide.filter.Filter;
 import org.apache.sling.ide.filter.FilterResult;
+import org.apache.sling.ide.transport.RepositoryPath;
 
 public class VltFilter implements Filter {
 
@@ -42,18 +43,16 @@ public class VltFilter implements Filter {
     }
 
     @Override
-    public FilterResult filter(String relativeFilePath) {
+    public FilterResult filter(RepositoryPath repositoryPath) {
+        
+        String pathAsString = repositoryPath.asString();
 
-        if (relativeFilePath.length() > 0 && relativeFilePath.charAt(0) != 
'/') {
-            relativeFilePath = '/' + relativeFilePath;
-        }
-
-        if (filter.contains(relativeFilePath)) {
+        if (filter.contains(pathAsString)) {
             return FilterResult.ALLOW;
         }
 
         for (PathFilterSet pathFilterSet : filter.getFilterSets()) {
-            if (pathFilterSet.getRoot().startsWith(relativeFilePath)) {
+            if (pathFilterSet.getRoot().startsWith(pathAsString)) {
                 return FilterResult.PREREQUISITE;
             }
         }
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandler.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandler.java
index 79c25f95..ab1ad71c 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandler.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandler.java
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.util.ISO8601;
 import org.apache.jackrabbit.vault.fs.io.DocViewParserHandler;
 import org.apache.jackrabbit.vault.util.DocViewNode2;
 import org.apache.jackrabbit.vault.util.DocViewProperty2;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 
 public class ResourceProxyParserHandler implements DocViewParserHandler {
@@ -73,7 +74,7 @@ public class ResourceProxyParserHandler implements 
DocViewParserHandler {
        public void startDocViewNode(String nodePath, DocViewNode2 docViewNode, 
Optional<DocViewNode2> parentDocViewNode,
                        int line, int column) throws IOException, 
RepositoryException {
                
-               ResourceProxy currentResource = new ResourceProxy(nodePath);
+               ResourceProxy currentResource = new ResourceProxy(new 
RepositoryPath(nodePath));
                for (DocViewProperty2 property: docViewNode.getProperties()) {
                        Object value = 
TypeHint.convertDocViewPropertyToTypedValue(property);
                        if (value != null) {
@@ -102,11 +103,13 @@ public class ResourceProxyParserHandler implements 
DocViewParserHandler {
      */
     static enum TypeHint {
         UNDEFINED(PropertyType.UNDEFINED) {
+            @Override
             Object parseValues(String[] values, boolean explicitMultiValue) {
                 return STRING.parseValues(values, explicitMultiValue);
             }
         },
         STRING(PropertyType.STRING) {
+            @Override
             Object parseValues(String[] values, boolean explicitMultiValue) {
                 if (values.length == 1 && !explicitMultiValue) {
                     return values[0];
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationDataBuilder.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationDataBuilder.java
index a00e9f00..52ec8f10 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationDataBuilder.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationDataBuilder.java
@@ -134,7 +134,7 @@ public class VltSerializationDataBuilder implements 
SerializationDataBuilder {
 
             SerializationKind serializationKind = 
getSerializationKind(aggregate);
 
-            if (resource.getPath().equals("/") || serializationKind == 
SerializationKind.METADATA_PARTIAL
+            if (resource.getPath().asString().equals("/") || serializationKind 
== SerializationKind.METADATA_PARTIAL
                     || serializationKind == SerializationKind.FILE || 
serializationKind == SerializationKind.FOLDER) {
                 nameHint = Constants.DOT_CONTENT_XML;
             } else if (serializationKind == SerializationKind.METADATA_FULL) {
@@ -277,13 +277,13 @@ public class VltSerializationDataBuilder implements 
SerializationDataBuilder {
      */
     private List<Aggregate> findAggregateChain(ResourceProxy resource) throws 
IOException, RepositoryException {
 
-        VaultFile vaultFile = 
fs.getFile(PlatformNameFormat.getPlatformPath(resource.getPath()));
+        VaultFile vaultFile = 
fs.getFile(PlatformNameFormat.getPlatformPath(resource.getPath().asString()));
 
         if (vaultFile == null || vaultFile.getAggregate() == null) {
                 // this file might be a leaf aggregate of a vaultfile higher 
in the resource path ; so look for a
                 // parent higher
 
-            String parentPath = Text.getRelativeParent(resource.getPath(), 1);
+            String parentPath = resource.getPath().getParent().asString();
             while (!parentPath.equals("/")) {
                 VaultFile parentFile = 
fs.getFile(PlatformNameFormat.getPlatformPath(parentPath));
 
@@ -335,10 +335,10 @@ public class VltSerializationDataBuilder implements 
SerializationDataBuilder {
         }
 
         for (Aggregate leaf : leaves) {
-            if (leaf.getPath().equals(resource.getPath())) {
+            if (leaf.getPath().equals(resource.getPath().asString())) {
                 chain.add(leaf);
                 return chain;
-            } else if (Text.isDescendant(leaf.getPath(), resource.getPath())) {
+            } else if (Text.isDescendant(leaf.getPath(), 
resource.getPath().asString())) {
                 chain.add(leaf);
                 return lookForAggregateInLeaves(resource, leaf, chain);
             }
diff --git 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManager.java
 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManager.java
index d3c0973c..8ebc8a35 100644
--- 
a/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManager.java
+++ 
b/shared/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManager.java
@@ -47,6 +47,7 @@ import org.apache.sling.ide.sync.content.WorkspaceFile;
 import org.apache.sling.ide.sync.content.WorkspacePath;
 import org.apache.sling.ide.sync.content.WorkspaceProject;
 import org.apache.sling.ide.sync.content.WorkspaceResource;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -153,7 +154,7 @@ public class VltSerializationManager implements 
SerializationManager {
     }
 
     @Override
-    public String getRepositoryPath(WorkspacePath localPath) {
+    public RepositoryPath getRepositoryPath(WorkspacePath localPath) {
 
         String osPath = localPath.asPortableString();
         String repositoryPath;
@@ -182,7 +183,7 @@ public class VltSerializationManager implements 
SerializationManager {
             repositoryPath = "/";
         }
 
-        return repositoryPath;
+        return new RepositoryPath(repositoryPath);
     }
 
     @Override
@@ -207,12 +208,12 @@ public class VltSerializationManager implements 
SerializationManager {
         if (file == null || ! file.exists() )
             return null;
 
-        String repositoryPath = 
getRepositoryPath(file.getPathRelativeToSyncDir());
+        RepositoryPath repositoryPath = 
getRepositoryPath(file.getPathRelativeToSyncDir());
 
         try (InputStream source = file.getContents()) {
                DocViewParser parser = new DocViewParser();
                ResourceProxyParserHandler handler = new 
ResourceProxyParserHandler();
-               parser.parse(repositoryPath, new InputSource(source), handler);
+               parser.parse(repositoryPath.asString(), new 
InputSource(source), handler);
             return handler.getRoot();
         } catch (XmlParseException e) {
             // TODO proper error handling
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommandIT.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommandIT.java
index 4e6e0015..2a87a4fa 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommandIT.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/AddOrUpdateNodeCommandIT.java
@@ -30,6 +30,7 @@ import org.apache.sling.ide.filter.Filter;
 import org.apache.sling.ide.filter.FilterResult;
 import org.apache.sling.ide.log.Logger;
 import org.apache.sling.ide.transport.CommandContext;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.hamcrest.Matchers;
 import org.junit.Ignore;
@@ -40,7 +41,7 @@ public class AddOrUpdateNodeCommandIT {
 
        private static final CommandContext DEFAULT_CONTEXT = new 
CommandContext(new Filter() {
                @Override
-               public FilterResult filter(String repositoryPath) {
+               public FilterResult filter(RepositoryPath repositoryPath) {
                        return FilterResult.ALLOW;
                }
        });
@@ -60,7 +61,7 @@ public class AddOrUpdateNodeCommandIT {
 
        private ResourceProxy newResource(String path, String primaryType) {
 
-               ResourceProxy resource = new ResourceProxy(path);
+               ResourceProxy resource = new ResourceProxy(new 
RepositoryPath(path));
                resource.addProperty("jcr:primaryType", primaryType);
                return resource;
        }
@@ -207,8 +208,8 @@ public class AddOrUpdateNodeCommandIT {
                final CommandContext context = new CommandContext(new Filter() {
 
                        @Override
-                       public FilterResult filter(String repositoryPath) {
-                               if 
(repositoryPath.equals("/content/not-included-child")) {
+                       public FilterResult filter(RepositoryPath 
repositoryPath) {
+                               if 
(repositoryPath.asString().equals("/content/not-included-child")) {
                                        return FilterResult.DENY;
                                }
 
@@ -281,7 +282,7 @@ public class AddOrUpdateNodeCommandIT {
        public void 
createIfRequiredFlagCreatesNeededResourcesEvenWhenPrimaryTypeIsMissing() throws 
Exception {
 
                Session session = repositoryManager.getAdminSession();
-               ResourceProxy resource = new ResourceProxy("/content");
+               ResourceProxy resource = new ResourceProxy(new 
RepositoryPath("/content"));
 
                AddOrUpdateNodeCommand cmd = new 
AddOrUpdateNodeCommand(repositoryManager.getRepository(), 
repositoryManager.getAdminCredentials(), DEFAULT_CONTEXT, null,
                                resource, logger, CREATE_ONLY_WHEN_MISSING);
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommandIT.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommandIT.java
index 25a7e26f..d8946b43 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommandIT.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/ReorderChildNodesCommandIT.java
@@ -28,6 +28,7 @@ import javax.jcr.NodeIterator;
 import javax.jcr.Session;
 
 import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.junit.Rule;
 import org.junit.Test;
@@ -115,7 +116,7 @@ public class ReorderChildNodesCommandIT {
 
     private ResourceProxy newResource(String path, String primaryType) {
 
-        ResourceProxy resource = new ResourceProxy(path);
+        ResourceProxy resource = new ResourceProxy(new RepositoryPath(path));
         resource.addProperty("jcr:primaryType", primaryType);
         return resource;
     }
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/filter/VltFilterTest.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/filter/VltFilterTest.java
index 478afb52..5d51e13d 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/filter/VltFilterTest.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/filter/VltFilterTest.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 
 import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
 import org.apache.sling.ide.filter.FilterResult;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.junit.Test;
 
 public class VltFilterTest {
@@ -31,7 +32,7 @@ public class VltFilterTest {
     @Test
     public void defaultFilterExcludedVarClasses() throws IOException, 
ConfigurationException {
 
-        assertThat(newFilter("filter-default.xml").filter("/var/classes"), 
is(FilterResult.DENY));
+        assertThat(newFilter("filter-default.xml").filter(new 
RepositoryPath("/var/classes")), is(FilterResult.DENY));
         
     }
 
@@ -48,20 +49,14 @@ public class VltFilterTest {
 
         VltFilter filter = new VltFilter(null);
 
-        assertThat(filter.filter("/var/classes"), is(FilterResult.DENY));
+        assertThat(filter.filter(new RepositoryPath("/var/classes")), 
is(FilterResult.DENY));
 
     }
 
     @Test
     public void defaultFilterIncludesLibs() throws IOException, 
ConfigurationException {
 
-        assertThat(newFilter("filter-default.xml").filter("/libs"), 
is(FilterResult.ALLOW));
-    }
-
-    @Test
-    public void pathMissingLeadingSlashIsCorrected() throws IOException, 
ConfigurationException {
-
-        assertThat(newFilter("filter-default.xml").filter("libs"), 
is(FilterResult.ALLOW));
+        assertThat(newFilter("filter-default.xml").filter(new 
RepositoryPath("/libs")), is(FilterResult.ALLOW));
     }
 
     @Test
@@ -69,7 +64,7 @@ public class VltFilterTest {
 
         String[] parents = new String[] { "/libs", "/libs/sling", 
"/libs/sling/servlet" };
         for (String parent : parents) {
-            assertThat("Parent '" + parent + "'", 
newFilter("filter-deep.xml").filter(parent),
+            assertThat("Parent '" + parent + "'", 
newFilter("filter-deep.xml").filter(new RepositoryPath(parent)),
                     is(FilterResult.PREREQUISITE));
         }
     }
@@ -77,9 +72,9 @@ public class VltFilterTest {
     @Test
     public void filterWithInclude() throws IOException, ConfigurationException 
{
         
-        
assertThat(newFilter("filter-with-include.xml").filter("/etc/designs/base"), 
is(FilterResult.PREREQUISITE));
-        
assertThat(newFilter("filter-with-include.xml").filter("/etc/designs/base/jcr:content"),
 is(FilterResult.ALLOW));
-        
assertThat(newFilter("filter-with-include.xml").filter("/etc/designs/base/other"),
 is(FilterResult.DENY));
+        assertThat(newFilter("filter-with-include.xml").filter(new 
RepositoryPath("/etc/designs/base")), is(FilterResult.PREREQUISITE));
+        assertThat(newFilter("filter-with-include.xml").filter(new 
RepositoryPath("/etc/designs/base/jcr:content")), is(FilterResult.ALLOW));
+        assertThat(newFilter("filter-with-include.xml").filter(new 
RepositoryPath("/etc/designs/base/other")), is(FilterResult.DENY));
     }
 
 }
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandlerTest.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandlerTest.java
index 8f4dfc5f..5a4c8a53 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandlerTest.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/ResourceProxyParserHandlerTest.java
@@ -28,13 +28,9 @@ import java.math.BigDecimal;
 import java.util.Calendar;
 import java.util.Map;
 
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
 import org.apache.jackrabbit.vault.fs.io.DocViewParser;
 import org.apache.jackrabbit.vault.fs.io.DocViewParser.XmlParseException;
-import org.apache.sling.ide.impl.vlt.Slf4jLogger;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
@@ -42,7 +38,6 @@ import org.hamcrest.Matchers;
 import org.hamcrest.TypeSafeMatcher;
 import org.junit.Test;
 import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
 
 public class ResourceProxyParserHandlerTest {
 
@@ -127,20 +122,20 @@ public class ResourceProxyParserHandlerTest {
 
         ResourceProxy root = parseContentXmlFile("full-coverage.xml", 
"/apps/full-coverage");
 
-        assertThat("full-coverage path", root.getPath(), 
is("/apps/full-coverage"));
+        assertThat("full-coverage path", root.getPath(), is(new 
RepositoryPath("/apps/full-coverage")));
         assertThat("full-coverage properties.size", 
root.getProperties().size(), is(3));
         assertThat("full-coverage properties[jcr:title]", root.getProperties(),
                 hasEntry("jcr:title", (Object) "Full coverage parent"));
         assertThat("full-coverage children.size", root.getChildren().size(), 
is(2));
 
         ResourceProxy parent1 = root.getChildren().get(0);
-        assertThat("parent-1 path", parent1.getPath(), 
is("/apps/full-coverage/parent-1"));
+        assertThat("parent-1 path", parent1.getPath(), is(new 
RepositoryPath("/apps/full-coverage/parent-1")));
         assertThat("parent-1 properties[jcr:title]", parent1.getProperties(),
                 hasEntry("jcr:title", (Object) "Parent 1"));
         assertThat("parent-1 children.size", parent1.getChildren().size(), 
is(2));
 
         ResourceProxy child11 = parent1.getChildren().get(0);
-        assertThat("child-1-1 path", child11.getPath(), 
is("/apps/full-coverage/parent-1/child-1-1"));
+        assertThat("child-1-1 path", child11.getPath(), is(new 
RepositoryPath("/apps/full-coverage/parent-1/child-1-1")));
         assertThat("child-1-1 properties[jcr:title]", child11.getProperties(),
                 hasEntry("jcr:title", (Object) "Child 1-1"));
 
@@ -246,11 +241,11 @@ public class ResourceProxyParserHandlerTest {
 
     static class ResourceChildPathMatcher extends TypeSafeMatcher<Iterable<? 
extends ResourceProxy>> {
 
-        private final String resourcePath;
+        private final RepositoryPath resourcePath;
 
         private ResourceChildPathMatcher(String resourcePath) {
 
-            this.resourcePath = resourcePath;
+            this.resourcePath = new RepositoryPath(resourcePath);
         }
 
         @Override
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManagerTest.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManagerTest.java
index 9375215b..9f414441 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManagerTest.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/serialization/VltSerializationManagerTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertThat;
 
 import org.apache.sling.ide.impl.vlt.Slf4jLogger;
 import org.apache.sling.ide.sync.content.WorkspacePath;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -60,18 +61,20 @@ public class VltSerializationManagerTest {
 
     @Test
     public void getRepositoryPath_CleanName() {
-        assertThat(serializationManager.getRepositoryPath(new 
WorkspacePath("/content/test")), is("/content/test"));
+        assertThat(serializationManager.getRepositoryPath(new 
WorkspacePath("/content/test")), 
+                is(new RepositoryPath("/content/test")));
     }
 
     @Test
     public void getRepositoryPath_MangledName() {
         assertThat(serializationManager.getRepositoryPath(new 
WorkspacePath("/content/test/_jcr_content")),
-                is("/content/test/jcr:content"));
+                is(new RepositoryPath("/content/test/jcr:content")));
     }
 
     @Test
     public void getRepositoryPath_SerializationDir() {
-        assertThat(serializationManager.getRepositoryPath(new 
WorkspacePath("/content/test.dir/file")), is("/content/test/file"));
+        assertThat(serializationManager.getRepositoryPath(new 
WorkspacePath("/content/test.dir/file")), 
+                is(new RepositoryPath("/content/test/file")));
     }
 
 }
diff --git 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/transport/DefaultBatcherTest.java
 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/transport/DefaultBatcherTest.java
index 4e705295..11d642bf 100644
--- 
a/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/transport/DefaultBatcherTest.java
+++ 
b/shared/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/transport/DefaultBatcherTest.java
@@ -32,6 +32,7 @@ import org.apache.sling.ide.impl.vlt.DeleteNodeCommand;
 import org.apache.sling.ide.impl.vlt.GetNodeContentCommand;
 import org.apache.sling.ide.impl.vlt.ReorderChildNodesCommand;
 import org.apache.sling.ide.transport.Command;
+import org.apache.sling.ide.transport.RepositoryPath;
 import org.apache.sling.ide.transport.ResourceProxy;
 import org.apache.sling.ide.transport.impl.DefaultBatcher;
 import org.hamcrest.Matchers;
@@ -69,9 +70,9 @@ public class DefaultBatcherTest {
     
     private void testMoreComprehensiveDeletesAreCompacted(String expected, 
String firstPath, String... otherPaths) {
 
-        batcher.add(new DeleteNodeCommand(mockRepo, credentials, firstPath, 
null));
+        batcher.add(new DeleteNodeCommand(mockRepo, credentials, new 
RepositoryPath(firstPath), null));
         for ( String otherPath: otherPaths) {
-            batcher.add(new DeleteNodeCommand(mockRepo, credentials, 
otherPath, null));
+            batcher.add(new DeleteNodeCommand(mockRepo, credentials, new 
RepositoryPath(otherPath), null));
         }
         
         List<Command<?>> batched = batcher.get();
@@ -79,14 +80,14 @@ public class DefaultBatcherTest {
         assertThat(batched, hasSize(1));
         Command<?> command = batched.get(0);
         assertThat(command, instanceOf(DeleteNodeCommand.class));
-        assertThat(command.getPath(), equalTo(expected));
+        assertThat(command.getPath().asString(), equalTo(expected));
     }
 
     @Test
     public void unrelatedDeletesAreNotCompacted() {
         
-        assertCommandsAreNotCompacted(new DeleteNodeCommand(mockRepo, 
credentials, "/content/branch", null), 
-                new DeleteNodeCommand(mockRepo, credentials, "/content/sub", 
null));
+        assertCommandsAreNotCompacted(new DeleteNodeCommand(mockRepo, 
credentials, new RepositoryPath("/content/branch"), null), 
+                new DeleteNodeCommand(mockRepo, credentials, new 
RepositoryPath("/content/sub"), null));
     }
     
     public void assertCommandsAreNotCompacted(Command<?> first, Command<?> 
second) {
@@ -104,7 +105,7 @@ public class DefaultBatcherTest {
     
     @Test
     public void dataIsClearedBetweenCalls() {
-        batcher.add(new DeleteNodeCommand(mockRepo, credentials, 
"/content/branch", null));
+        batcher.add(new DeleteNodeCommand(mockRepo, credentials, new 
RepositoryPath("/content/branch"), null));
         batcher.get();
         assertThat(batcher.get(), hasSize(0));
     }
@@ -112,8 +113,8 @@ public class DefaultBatcherTest {
     @Test
     public void identicalAddOrUpdatesAreCompacted() {
         
-        AddOrUpdateNodeCommand first = new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, new ResourceProxy("/content"), null);
-        AddOrUpdateNodeCommand second = new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, new ResourceProxy("/content"), null);
+        AddOrUpdateNodeCommand first = new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, newResource("/content"), null);
+        AddOrUpdateNodeCommand second = new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, newResource("/content"), null);
         
         batcher.add(first);
         batcher.add(second);
@@ -123,22 +124,22 @@ public class DefaultBatcherTest {
         assertThat(batched, hasSize(1));
         Command<?> command = batched.get(0);
         assertThat(command, instanceOf(AddOrUpdateNodeCommand.class));
-        assertThat(command.getPath(), equalTo("/content"));
+        assertThat(command.getPath().asString(), equalTo("/content"));
         
     }
 
     @Test
     public void unrelatedAddOrUpdatesAreNotCompacted() {
         
-        assertCommandsAreNotCompacted(new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, new ResourceProxy("/content/a"), null), 
-                new AddOrUpdateNodeCommand(mockRepo, credentials, null, null, 
new ResourceProxy("/content/b"), null));
+        assertCommandsAreNotCompacted(new AddOrUpdateNodeCommand(mockRepo, 
credentials, null, null, newResource("/content/a"), null), 
+                new AddOrUpdateNodeCommand(mockRepo, credentials, null, null, 
newResource("/content/b"), null));
     }
 
     @Test
     public void identicalsReorderingsAreCompacted() {
         
-        ReorderChildNodesCommand first = new 
ReorderChildNodesCommand(mockRepo, credentials, new ResourceProxy("/content"), 
null);
-        ReorderChildNodesCommand second = new 
ReorderChildNodesCommand(mockRepo, credentials,new ResourceProxy("/content"), 
null);
+        ReorderChildNodesCommand first = new 
ReorderChildNodesCommand(mockRepo, credentials, newResource("/content"), null);
+        ReorderChildNodesCommand second = new 
ReorderChildNodesCommand(mockRepo, credentials,newResource("/content"), null);
         
         batcher.add(first);
         batcher.add(second);
@@ -148,20 +149,24 @@ public class DefaultBatcherTest {
         assertThat(batched, hasSize(1));
         Command<?> command = batched.get(0);
         assertThat(command, instanceOf(ReorderChildNodesCommand.class));
-        assertThat(command.getPath(), equalTo("/content"));
+        assertThat(command.getPath().asString(), equalTo("/content"));
     }
     
     @Test
     public void unrelatedReorderingsAreNotCompacted() {
         
-        assertCommandsAreNotCompacted(new ReorderChildNodesCommand(mockRepo, 
credentials, new ResourceProxy("/content/a"), null), 
-                new ReorderChildNodesCommand(mockRepo, credentials,new 
ResourceProxy("/content/b"), null));
+        assertCommandsAreNotCompacted(new ReorderChildNodesCommand(mockRepo, 
credentials, newResource("/content/a"), null), 
+                new ReorderChildNodesCommand(mockRepo, 
credentials,newResource("/content/b"), null));
     }
     
     @Test
     public void unhandledCommandIsReturnedAsIs() {
         
-        assertCommandsAreNotCompacted(new GetNodeContentCommand(mockRepo, 
credentials, "/content", null), 
-                new GetNodeContentCommand(mockRepo, credentials, "/content", 
null));
+        assertCommandsAreNotCompacted(new GetNodeContentCommand(mockRepo, 
credentials, new RepositoryPath("/content"), null), 
+                new GetNodeContentCommand(mockRepo, credentials, new 
RepositoryPath("/content"), null));
+    }
+    
+    private ResourceProxy newResource(String path) {
+        return new ResourceProxy(new RepositoryPath(path));
     }
 }
diff --git 
a/shared/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
 
b/shared/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
index 6b35f08b..24fce798 100644
--- 
a/shared/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
+++ 
b/shared/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
@@ -24,13 +24,14 @@ import java.nio.file.Paths;
 import org.apache.sling.ide.filter.Filter;
 import org.apache.sling.ide.filter.FilterLocator;
 import org.apache.sling.ide.filter.FilterResult;
+import org.apache.sling.ide.transport.RepositoryPath;
 
 public class MockFilterLocator implements FilterLocator {
 
     public static final Filter MOCK_FILTER = new Filter() {
         
         @Override
-        public FilterResult filter(String repositoryPath) {
+        public FilterResult filter(RepositoryPath repositoryPath) {
             return FilterResult.ALLOW;
         }
     };

Reply via email to