You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2018/04/18 14:55:00 UTC

[sling-ide-tooling] branch feature/SLING-7587 updated (965d93b -> c5c6da4)

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

rombert pushed a change to branch feature/SLING-7587
in repository https://gitbox.apache.org/repos/asf/sling-ide-tooling.git.


    from 965d93b  SLING-7587 - Create a CLI-only tool to sync content
     new ca9b79c  DefaultSyncCommandFactory: remove unused import.
     new 343e3ac  SLING-7587 - Create a CLI-only tool to sync content
     new 67c5010  SLING-7587 - Create a CLI-only tool to sync content
     new c5c6da4  SLING-7587 - Create a CLI-only tool to sync content

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 cli/cli/bnd.bnd                                    |   1 +
 {shared/modules/api => cli/cli}/pom.xml            |  54 +++---
 .../org/apache/sling/ide/cli/impl/ContentSync.java | 128 +++++++++++++
 .../org/apache/sling/ide/cli/impl/DirWatcher.java  | 202 +++++++++++++++++++++
 .../sling/ide/cli/impl/Slf4jLoggerFactory.java     |  41 +++--
 .../apache/sling/ide/cli/impl/DirWatcherTest.java  | 177 ++++++++++++++++++
 cli/dist/.gitignore                                |   3 +
 cli/dist/assemble-app.sh                           |   5 +
 cli/dist/features/clisync.json                     |  28 +++
 {shared/modules/sync-fs => cli/dist}/pom.xml       |  42 ++---
 cli/dist/run-app.sh                                |   5 +
 {shared/modules => cli}/pom.xml                    |  12 +-
 .../content/impl/DefaultSyncCommandFactory.java    |   1 -
 .../sling/ide/impl/vlt/VltRepositoryFactory.java   |   2 +-
 shared/modules/sync-fs/bnd.bnd                     |   1 +
 shared/modules/sync-fs/pom.xml                     |   9 +
 .../sling/ide/content/sync/fs/FSResources.java}    |  21 +--
 .../content/sync/fs/impl/FSWorkspaceProject.java   |   2 +-
 .../sling/ide/content/sync/fs}/package-info.java   |   3 +-
 .../content/sync/fs/impl/MockFilterLocator.java    |   2 +-
 20 files changed, 647 insertions(+), 92 deletions(-)
 create mode 100644 cli/cli/bnd.bnd
 copy {shared/modules/api => cli/cli}/pom.xml (73%)
 create mode 100644 cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java
 create mode 100644 cli/cli/src/main/java/org/apache/sling/ide/cli/impl/DirWatcher.java
 copy shared/modules/impl-vlt/src/test/java/org/apache/sling/ide/impl/vlt/Slf4jLogger.java => cli/cli/src/main/java/org/apache/sling/ide/cli/impl/Slf4jLoggerFactory.java (69%)
 create mode 100644 cli/cli/src/test/java/org/apache/sling/ide/cli/impl/DirWatcherTest.java
 create mode 100644 cli/dist/.gitignore
 create mode 100755 cli/dist/assemble-app.sh
 create mode 100644 cli/dist/features/clisync.json
 copy {shared/modules/sync-fs => cli/dist}/pom.xml (69%)
 create mode 100755 cli/dist/run-app.sh
 copy {shared/modules => cli}/pom.xml (84%)
 create mode 100644 shared/modules/sync-fs/bnd.bnd
 copy shared/modules/{api/src/main/java/org/apache/sling/ide/sync/content/WorkspacePaths.java => sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/FSResources.java} (64%)
 copy shared/modules/{api/src/main/java/org/apache/sling/ide/sync/content => sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs}/package-info.java (94%)

-- 
To stop receiving notification emails like this one, please contact
rombert@apache.org.

[sling-ide-tooling] 04/04: SLING-7587 - Create a CLI-only tool to sync content

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c5c6da4e429c990ca6281e2217e81a596bfa1a93
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Apr 17 15:09:03 2018 +0300

    SLING-7587 - Create a CLI-only tool to sync content
    
    Add a CLI reactor which includes a CLI bundle and a CLI distribution (WIP)
    based on the feature model.
---
 cli/cli/bnd.bnd                                    |   1 +
 cli/cli/pom.xml                                    | 107 +++++++++++
 .../org/apache/sling/ide/cli/impl/ContentSync.java | 128 +++++++++++++
 .../org/apache/sling/ide/cli/impl/DirWatcher.java  | 202 +++++++++++++++++++++
 .../sling/ide/cli/impl/Slf4jLoggerFactory.java     |  84 +++++++++
 .../apache/sling/ide/cli/impl/DirWatcherTest.java  | 177 ++++++++++++++++++
 cli/dist/.gitignore                                |   3 +
 cli/dist/assemble-app.sh                           |   5 +
 cli/dist/features/clisync.json                     |  28 +++
 cli/dist/pom.xml                                   |  76 ++++++++
 cli/dist/run-app.sh                                |   5 +
 cli/pom.xml                                        |  39 ++++
 12 files changed, 855 insertions(+)

diff --git a/cli/cli/bnd.bnd b/cli/cli/bnd.bnd
new file mode 100644
index 0000000..1e09af3
--- /dev/null
+++ b/cli/cli/bnd.bnd
@@ -0,0 +1 @@
+-exportcontents: ${packages;VERSIONED}
\ No newline at end of file
diff --git a/cli/cli/pom.xml b/cli/cli/pom.xml
new file mode 100644
index 0000000..f6b83c0
--- /dev/null
+++ b/cli/cli/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>33</version>
+    </parent>
+
+    <artifactId>org.apache.sling.ide.cli</artifactId>
+    <name>Apache Sling IDE Tools CLI</name>
+    <version>1.2.3-SNAPSHOT</version>
+
+    <scm>
+        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</connection>
+        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</developerConnection>
+        <url>https://gitbox.apache.org/repos/asf?p=sling-ide-tooling.git</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.event</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling.ide</groupId>
+            <artifactId>org.apache.sling.ide.api</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling.ide</groupId>
+            <artifactId>org.apache.sling.ide.sync-fs</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <version>1.3</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Note that OSGi annotations are OK since they are not retained at compile time -->        
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.annotation.versioning</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.metatype.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <properties>
+        <sling.java.version>8</sling.java.version>
+    </properties>
+    <groupId>org.apache.sling.ide</groupId>
+</project>
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
new file mode 100644
index 0000000..9924ced
--- /dev/null
+++ b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/ContentSync.java
@@ -0,0 +1,128 @@
+/*
+ * 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.cli.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+
+import org.apache.sling.ide.cli.impl.DirWatcher.Event;
+import org.apache.sling.ide.content.sync.fs.FSResources;
+import org.apache.sling.ide.filter.FilterLocator;
+import org.apache.sling.ide.log.Logger;
+import org.apache.sling.ide.sync.content.SyncCommandFactory;
+import org.apache.sling.ide.sync.content.WorkspacePath;
+import org.apache.sling.ide.sync.content.WorkspacePaths;
+import org.apache.sling.ide.sync.content.WorkspaceProject;
+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.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(immediate=true)
+public class ContentSync {
+    
+    @Reference
+    private Logger logger;
+    
+    @Reference
+    private RepositoryFactory repoFactory;
+    
+    @Reference
+    private SyncCommandFactory commandFactory;
+    
+    @Reference
+    private FilterLocator filterLocator;
+    
+    private DirWatcher watcher;
+    
+    private Thread watcherThread;
+    
+
+    protected void activate() throws Exception {
+
+        File projectDir = new File("/home/robert/Documents/workspace/content003");
+        
+        WorkspaceProject prj = FSResources.create(projectDir, projectDir, filterLocator);
+        
+        logger.trace("Working on project {0} at {1}", prj.getName(), prj.getOSPath());
+        
+        Repository repo = repoFactory.connectRepository(new RepositoryInfo("admin", "admin", "http://localhost:8080"));
+        
+        repo.newListChildrenNodeCommand("/").execute();
+        
+        logger.trace("Connected to {0} ", repo.getRepositoryInfo());
+        
+        Path syncDirPath = prj.getSyncDirectory().getOSPath();
+        
+        watcher = new DirWatcher(syncDirPath);
+        
+        logger.trace("Watching syncDir {0}", syncDirPath);
+        
+        watcherThread = new Thread(new Runnable()  {
+            @Override
+            public void run() {
+                try {
+                    while ( ! Thread.currentThread().isInterrupted() ) {
+
+                        Event event = watcher.poll();
+            
+                        Path path = event.getPath();
+                        
+                        WorkspacePath resourceRelativePath = WorkspacePaths.fromOsPath(path);
+                        logger.trace("Change detected in workspace path {0}", resourceRelativePath);
+                        if ( event.getKind() == StandardWatchEventKinds.ENTRY_CREATE || 
+                                event.getKind() == StandardWatchEventKinds.ENTRY_MODIFY ) {
+                            try {
+                                Command<?> cmd = commandFactory.
+                                    newCommandForAddedOrUpdatedResource(repo, prj.getSyncDirectory().getFile(resourceRelativePath));
+                                if ( cmd != null )
+                                    cmd.execute();
+                            } catch (IOException e) {
+                                logger.warn("Sync failed for path " + resourceRelativePath , e);
+                            }
+                        }
+                        
+                        if ( event.getKind() == StandardWatchEventKinds.ENTRY_DELETE ) {
+                            try {
+                                Command<?> cmd = commandFactory.newCommandForRemovedResource(repo, prj.getSyncDirectory().getFile(resourceRelativePath));
+                                if ( cmd != null )
+                                    cmd.execute();
+                            } catch (IOException e) {
+                                logger.warn("Sync failed for path " + resourceRelativePath , e);
+                            }
+                        }
+                    }
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        });
+        
+        watcherThread.start();
+    }
+    
+    protected void deactivate() throws Exception {
+        
+        if ( watcher != null ) {
+            watcherThread.interrupt();
+        }
+    }
+}
diff --git a/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/DirWatcher.java b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/DirWatcher.java
new file mode 100644
index 0000000..8eb9795
--- /dev/null
+++ b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/DirWatcher.java
@@ -0,0 +1,202 @@
+/*
+ * 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.cli.impl;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchEvent.Kind;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Watches a whole directory tree for changes
+ * 
+ * <p>This class works on top of the standard  {@link WatchService} API by generating
+ * events for all changes below a given directory.</p>
+ */
+public class DirWatcher implements AutoCloseable {
+    
+    private final Path root;
+    private final WatchService ws;
+    private final DualMap watched = new DualMap();
+    private final Thread poller;
+    private final BlockingQueue<DirWatcher.Event> queue = new LinkedBlockingQueue<>();
+
+    public DirWatcher(Path path) throws IOException {
+        this.root = path;
+        ws = path.getFileSystem().newWatchService();
+
+        poller = new Thread(() ->  {
+            while ( !Thread.currentThread().isInterrupted() ) {
+                try {
+                    queue.addAll(pollInternal());
+                } catch ( InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    break;
+                }
+            }
+        }, getClass().getSimpleName() +"-Poller");
+        
+        Stream.concat(
+            Stream.of(root),
+            Files.walk(root).filter(p -> p.toFile().isDirectory())
+        ).forEach( this::register);
+        
+        poller.start();
+    }
+    
+    public void close() throws IOException {
+        if ( poller != null )
+            poller.interrupt();
+        if ( ws != null)
+            ws.close();
+    }
+
+    /**
+     * Takes a single event from the queue, blocking if none are available
+     * 
+     * @return the event
+     * @throws InterruptedException interrupted
+     */
+    public Event poll() throws InterruptedException {
+        return queue.take();
+    }
+    
+    // visible for testing
+    int queueSize() {
+        return queue.size();
+    }
+    
+    private void register(Path path) {
+        try {
+            WatchKey key = path.register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+            watched.put(key, path);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void unregister(Path path) {
+        WatchKey key = watched.remove(path);
+        if ( key != null )
+            key.cancel();
+        
+    }
+    
+    private List<DirWatcher.Event> pollInternal() throws InterruptedException {
+        final WatchKey key = ws.take();
+        
+        List<DirWatcher.Event> result = key.pollEvents().stream()
+            .filter( e -> e.context() instanceof Path )
+            .map( Event::new )
+            .map( e -> updateTracked(e, key) )
+            .map( e -> adjust(e, key) )
+            .collect( Collectors.toList() );
+        
+        key.reset();
+        
+        return result;
+    }
+
+    private DirWatcher.Event adjust(Event e, WatchKey key) {
+        Path keyPath = watched.get(key);
+        e.path = root.relativize(keyPath.resolve(e.path));
+        return e;
+    }
+    
+    private DirWatcher.Event updateTracked(DirWatcher.Event evt, WatchKey key) {
+        if ( evt.getKind() == StandardWatchEventKinds.ENTRY_CREATE ) {
+            Path fullPath = watched.get(key).resolve(evt.getPath());
+            if ( fullPath.toFile().isDirectory())
+                register(fullPath);            
+        } else if ( evt.getKind() == StandardWatchEventKinds.ENTRY_DELETE ) {
+            Path fullPath = watched.get(key).resolve(evt.getPath());
+            // we can't check if the path pointed to a directory since it is already deleted
+            unregister(fullPath);
+        }
+
+        return evt;
+    }
+    
+    public static class Event {
+        
+        public Event(WatchEvent<?> wrapper) {
+            kind = wrapper.kind();
+            path = (Path) wrapper.context();
+        }
+        
+        private Kind<?> kind;
+        private Path path;
+        
+        public Kind<?> getKind() {
+            return kind;
+        }
+        
+        public Path getPath() {
+            return path;
+        }
+    }
+    
+    static class DualMap {
+
+        private final Map<WatchKey, Path> forward = new HashMap<>();
+        private final Map<Path, WatchKey> reverse = new HashMap<>();
+        private final Object sync = new Object();
+        
+        public void put(WatchKey key, Path path) {
+            synchronized (sync) {
+                forward.put(key, path);
+                reverse.put(path, key);
+            }
+        }
+        
+        public Path get(WatchKey key) {
+            synchronized (sync) {
+                return forward.get(key);
+            }
+        }
+        
+        public WatchKey get(Path path) {
+            synchronized (sync) {
+                return reverse.get(path);
+            }
+        }
+        
+        public WatchKey remove(Path path) {
+            synchronized (sync) {
+                WatchKey key = reverse.get(path);
+                if ( key != null )
+                    forward.remove(key);
+                return key;
+            }
+        }
+    }
+}
diff --git a/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/Slf4jLoggerFactory.java b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/Slf4jLoggerFactory.java
new file mode 100644
index 0000000..288d142
--- /dev/null
+++ b/cli/cli/src/main/java/org/apache/sling/ide/cli/impl/Slf4jLoggerFactory.java
@@ -0,0 +1,84 @@
+/*
+ * 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.cli.impl;
+
+
+import org.apache.sling.ide.log.Logger;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ServiceScope;
+import org.slf4j.LoggerFactory;
+
+@Component(service = Logger.class, scope = ServiceScope.BUNDLE)
+public class Slf4jLoggerFactory implements Logger {
+
+    private static final long PERF_IGNORE_THRESHOLD = 50;
+
+    private final org.slf4j.Logger wrapped = LoggerFactory.getLogger(Slf4jLoggerFactory.class);
+
+    private String marker;
+    
+    protected void activate(ComponentContext ctx) {
+        marker = "[" + ctx.getUsingBundle().getSymbolicName() + "] ";
+        wrapped.info(marker + "Logger initialized");
+    }
+
+    @Override
+    public void warn(String message, Throwable cause) {
+        wrapped.warn( marker + message, cause);
+    }
+
+    @Override
+    public void warn(String message) {
+        wrapped.warn(marker + message);
+    }
+
+    @Override
+    public void trace(String message, Throwable error) {
+        wrapped.info(marker + message, error);
+    }
+
+    @Override
+    public void trace(String message, Object... arguments) {
+
+        // this is probably a horribly slow implementation, but it does not matter
+        for (int i = 0; i < arguments.length; i++) {
+            message = message.replace("{" + i + "}", String.valueOf(arguments[i]));
+        }
+
+        wrapped.info(marker + message);
+    }
+
+    @Override
+    public void error(String message, Throwable cause) {
+        wrapped.error(marker + message, cause);
+    }
+
+    @Override
+    public void error(String message) {
+        wrapped.error(marker + message);
+    }
+
+    @Override
+    public void tracePerformance(String message, long duration, Object... arguments) {
+        if (duration < PERF_IGNORE_THRESHOLD) {
+            return;
+        }
+        trace(message + " took " + duration + " ms", arguments);
+    }
+
+}
diff --git a/cli/cli/src/test/java/org/apache/sling/ide/cli/impl/DirWatcherTest.java b/cli/cli/src/test/java/org/apache/sling/ide/cli/impl/DirWatcherTest.java
new file mode 100644
index 0000000..4c6b173
--- /dev/null
+++ b/cli/cli/src/test/java/org/apache/sling/ide/cli/impl/DirWatcherTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.cli.impl;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class DirWatcherTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+    
+    @Test(timeout = 3000)
+    public void addedFileInRoot() throws IOException, InterruptedException {
+        
+        File watchRoot = folder.newFolder();
+        
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) {
+            
+            final File created = new File(watchRoot, "README");
+            created.createNewFile();
+            
+            DirWatcher.Event event = w.poll();
+            
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_CREATE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(created.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+    }
+    
+    @Test(timeout = 3000)
+    public void addedFileInSubdir() throws IOException, InterruptedException {
+        
+        File watchRoot = folder.newFolder();
+        File subDir = new File(watchRoot, "subDir");
+        subDir.mkdir();
+        
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) {
+            
+            File created = new File(subDir, "README");
+            created.createNewFile();
+    
+            DirWatcher.Event event = w.poll();
+            
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_CREATE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(subDir.getName(), created.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+
+    }
+    
+    @Test(timeout = 3000)
+    public void addedFileInNewSubdir() throws IOException, InterruptedException {
+
+        File watchRoot = folder.newFolder();
+        
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) {
+    
+            File subDir = new File(watchRoot, "subDir");
+            subDir.mkdir();
+    
+            DirWatcher.Event event = w.poll();
+            
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_CREATE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(subDir.getName())));
+            
+            File created = new File(subDir, "README");
+            created.createNewFile();
+            
+            event = w.poll();
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_CREATE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(subDir.getName(), created.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+    }
+    
+    @Test(timeout = 3000)
+    public void deletedFile() throws IOException, InterruptedException {
+        
+        File watchRoot = folder.newFolder();
+        File subDir = new File(watchRoot, "subDir");
+        subDir.mkdir();
+
+        File created = new File(subDir, "README");
+        created.createNewFile();
+
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) { 
+
+            created.delete();
+            
+            DirWatcher.Event event = w.poll();
+        
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_DELETE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(subDir.getName(), created.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+    }
+    
+    @Test(timeout = 300000)
+    public void deleteDir() throws IOException, InterruptedException {
+        
+        File watchRoot = folder.newFolder();
+        File subDir = new File(watchRoot, "subDir");
+        subDir.mkdir();
+
+
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) { 
+            
+            Files.delete(subDir.toPath());
+            
+            DirWatcher.Event event = w.poll();
+        
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_DELETE));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(subDir.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+    }
+
+    @Test(timeout = 3000)
+    public void modifyFile() throws IOException, InterruptedException {
+        
+        File watchRoot = folder.newFolder();
+        final File created = new File(watchRoot, "README");
+        created.createNewFile();        
+        
+        try ( DirWatcher w = new DirWatcher(watchRoot.toPath()) ) { 
+            
+            Files.write(created.toPath(), "hello, world".getBytes(UTF_8));
+            
+            DirWatcher.Event event = w.poll();
+            
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_MODIFY));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(created.getName())));
+            
+            Files.write(created.toPath(), "hello, again".getBytes(UTF_8));
+            
+            event = w.poll();
+            
+            assertThat("event.kind", event.getKind(), equalTo(ENTRY_MODIFY));
+            assertThat("event.path", event.getPath(), equalTo(Paths.get(created.getName())));
+            
+            assertThat("queue.size", w.queueSize(), equalTo(0));
+        }
+    }
+}
diff --git a/cli/dist/.gitignore b/cli/dist/.gitignore
new file mode 100644
index 0000000..952774f
--- /dev/null
+++ b/cli/dist/.gitignore
@@ -0,0 +1,3 @@
+/felix-cache/
+/launcher/
+/sling.json
diff --git a/cli/dist/assemble-app.sh b/cli/dist/assemble-app.sh
new file mode 100755
index 0000000..e869306
--- /dev/null
+++ b/cli/dist/assemble-app.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -rf felix-cache launcher
+
+java -cp  ../../../whiteboard/featuremodel/feature-applicationbuilder/target/org.apache.sling.feature.applicationbuilder-0.0.1-SNAPSHOT.jar:${HOME}/.m2/repository/org/apache/felix/org.apache.felix.framework/5.6.8/org.apache.felix.framework-5.6.8.jar   org.apache.sling.feature.applicationbuilder.impl.Main   -d features/   -u file://${HOME}/.m2/repository   -o sling.json
diff --git a/cli/dist/features/clisync.json b/cli/dist/features/clisync.json
new file mode 100644
index 0000000..0fb71fb
--- /dev/null
+++ b/cli/dist/features/clisync.json
@@ -0,0 +1,28 @@
+{
+	"id": "org.apache.sling.ide/org.apache.sling.ide.cli-dist/1.0.0",
+	"bundles": [
+		"org.apache.felix/org.apache.felix.eventadmin/1.4.10",
+		"org.slf4j/slf4j-api/1.7.25",
+		"org.slf4j/slf4j-simple/1.7.25",
+		"org.slf4j/jcl-over-slf4j/1.7.25",
+		"org.apache.felix/org.apache.felix.scr/2.0.12",
+		"org.apache.sling.ide/org.apache.sling.ide.api/1.2.3-SNAPSHOT",
+		"org.apache.sling.ide/org.apache.sling.ide.impl-vlt/1.2.3-SNAPSHOT",
+		"org.apache.sling.ide/org.apache.sling.ide.sync-fs/1.2.3-SNAPSHOT",
+		"org.apache.sling.ide/org.apache.sling.ide.cli/1.2.3-SNAPSHOT",
+		"org.apache.sling.ide/org.apache.sling.ide.vlt-wrapper/1.2.3-SNAPSHOT",
+		"javax.servlet/javax.servlet-api/3.1.0",
+		"commons-collections/commons-collections/3.2.2",
+		"org.apache.sling/org.apache.sling.fragment.xml/1.0.2",
+		"org.apache.geronimo.bundles/commons-httpclient/3.1_2",
+		"commons-codec/commons-codec/1.11",
+		"com.google.code.gson/gson/2.2.4",
+		"commons-io/commons-io/2.6",
+		"org.apache.felix/org.apache.felix.gogo.command/1.0.2",
+		"org.apache.felix/org.apache.felix.gogo.runtime/1.0.6",
+		"org.apache.felix/org.apache.felix.gogo.jline/1.0.0",
+		"org.apache.felix/org.apache.felix.gogo.shell/1.0.0",
+		"org.jline/jline/3.0.1",
+		"org.apache.geronimo.specs/geronimo-atinject_1.0_spec/1.0"
+	]
+}
\ No newline at end of file
diff --git a/cli/dist/pom.xml b/cli/dist/pom.xml
new file mode 100644
index 0000000..e99bdc4
--- /dev/null
+++ b/cli/dist/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>33</version>
+    </parent>
+
+    <artifactId>org.apache.sling.ide.cli-dist</artifactId>
+    <name>Apache Sling IDE Tools CLI distribution module</name>
+    <packaging>osgiapp</packaging>
+
+    <scm>
+        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</connection>
+        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</developerConnection>
+        <url>https://gitbox.apache.org/repos/asf?p=sling-ide-tooling.git</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>osgifeature-maven-plugin</artifactId>
+                <version>0.01.7-SNAPSHOT</version>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.event</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Note that OSGi annotations are OK since they are not retained at compile time -->        
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.annotation.versioning</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.component.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.metatype.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+    <properties>
+        <sling.java.version>8</sling.java.version>
+    </properties>
+</project>
diff --git a/cli/dist/run-app.sh b/cli/dist/run-app.sh
new file mode 100755
index 0000000..4571e12
--- /dev/null
+++ b/cli/dist/run-app.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -rf felix-cache launcher
+
+java -jar ../../../whiteboard/featuremodel/feature-launcher/target/org.apache.sling.feature.launcher-0.0.1-SNAPSHOT.jar -a sling.json
diff --git a/cli/pom.xml b/cli/pom.xml
new file mode 100644
index 0000000..fd40a59
--- /dev/null
+++ b/cli/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>14</version>
+    </parent>
+    <groupId>org.apache.sling.ide</groupId>
+    <artifactId>sling-ide-tooling-cli</artifactId>
+    <version>1.2.3-SNAPSHOT</version>
+    <packaging>pom</packaging>
+    <name>Apache Sling IDE Tools - CLI</name>
+    <url>http://sling.apache.org</url>
+
+    <scm>
+        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</connection>
+        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-ide-tooling.git</developerConnection>
+        <url>https://gitbox.apache.org/repos/asf?p=sling-ide-tooling.git</url>
+    </scm>
+
+    <modules>
+        <module>cli</module>
+        <module>dist</module>
+    </modules>
+</project>

-- 
To stop receiving notification emails like this one, please contact
rombert@apache.org.

[sling-ide-tooling] 01/04: DefaultSyncCommandFactory: remove unused import.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ca9b79c4c695892a2e8e690f7dc809318c5e40e4
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Wed Apr 18 17:45:28 2018 +0300

    DefaultSyncCommandFactory: remove unused import.
---
 .../apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/shared/modules/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java b/shared/modules/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
index ec222ad..f82504b 100644
--- a/shared/modules/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
+++ b/shared/modules/api/src/main/java/org/apache/sling/ide/sync/content/impl/DefaultSyncCommandFactory.java
@@ -27,7 +27,6 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.sling.ide.filter.FilterResult;
 import org.apache.sling.ide.log.Logger;

-- 
To stop receiving notification emails like this one, please contact
rombert@apache.org.

[sling-ide-tooling] 02/04: SLING-7587 - Create a CLI-only tool to sync content

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 343e3ac186c2bf48542a8b94c8053787f818f831
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Apr 17 15:09:03 2018 +0300

    SLING-7587 - Create a CLI-only tool to sync content
    
    VltRepositoryFactory - use a generic Logger. The registration property is no
    longer relevant as we will be using ServiceFactory instances.
---
 .../main/java/org/apache/sling/ide/impl/vlt/VltRepositoryFactory.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/shared/modules/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepositoryFactory.java b/shared/modules/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepositoryFactory.java
index 5b3dc00..760f54f 100644
--- a/shared/modules/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepositoryFactory.java
+++ b/shared/modules/impl-vlt/src/main/java/org/apache/sling/ide/impl/vlt/VltRepositoryFactory.java
@@ -38,7 +38,7 @@ public class VltRepositoryFactory implements RepositoryFactory {
     @Reference
     private EventAdmin eventAdmin;
     
-    @Reference(target = "(listener.symbolic.name=org.apache.sling.ide.impl-vlt)")
+    @Reference
     private Logger logger;
     
     private Map<String,VltRepository> repositoryMap = new HashMap<>();

-- 
To stop receiving notification emails like this one, please contact
rombert@apache.org.

[sling-ide-tooling] 03/04: SLING-7587 - Create a CLI-only tool to sync content

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 67c50101d7e85f97e4e3a8d448d4e58dfdcf0f4a
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Apr 17 15:09:03 2018 +0300

    SLING-7587 - Create a CLI-only tool to sync content
    
    sync-fs: bugfix and allow usage in OSGi environments
---
 shared/modules/sync-fs/bnd.bnd                     |  1 +
 shared/modules/sync-fs/pom.xml                     |  9 ++++++
 .../sling/ide/content/sync/fs/FSResources.java}    | 35 +++++-----------------
 .../content/sync/fs/impl/FSWorkspaceProject.java   |  2 +-
 .../sling/ide/content/sync/fs/package-info.java    | 18 +++++++++++
 .../content/sync/fs/impl/MockFilterLocator.java    |  2 +-
 6 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/shared/modules/sync-fs/bnd.bnd b/shared/modules/sync-fs/bnd.bnd
new file mode 100644
index 0000000..1e09af3
--- /dev/null
+++ b/shared/modules/sync-fs/bnd.bnd
@@ -0,0 +1 @@
+-exportcontents: ${packages;VERSIONED}
\ No newline at end of file
diff --git a/shared/modules/sync-fs/pom.xml b/shared/modules/sync-fs/pom.xml
index 43b7fe9..ce5177b 100644
--- a/shared/modules/sync-fs/pom.xml
+++ b/shared/modules/sync-fs/pom.xml
@@ -46,6 +46,15 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
diff --git a/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/FSResources.java
similarity index 50%
copy from shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
copy to shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/FSResources.java
index 85a935c..9185a69 100644
--- a/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
+++ b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/FSResources.java
@@ -14,40 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.ide.content.sync.fs.impl;
+package org.apache.sling.ide.content.sync.fs;
 
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Paths;
 
-import org.apache.sling.ide.filter.Filter;
+import org.apache.sling.ide.content.sync.fs.impl.FSWorkspaceProject;
 import org.apache.sling.ide.filter.FilterLocator;
-import org.apache.sling.ide.filter.FilterResult;
+import org.apache.sling.ide.sync.content.WorkspaceProject;
 
-public class MockFilterLocator implements FilterLocator {
+public abstract class FSResources {
 
-    public static final Filter MOCK_FILTER = new Filter() {
-        
-        @Override
-        public FilterResult filter(String repositoryPath) {
-            return FilterResult.ALLOW;
-        }
-    };
+    public static WorkspaceProject create(File projectDir, File syncRoot, FilterLocator filterLocator) {
+        return new FSWorkspaceProject(projectDir, syncRoot, filterLocator);
+    }
     
-    @Override
-    public File findFilterLocation(File syncDirectory) {
-        
-        return syncDirectory.toPath().
-                resolve(Paths.get("META-INF", "vault", "filter.xml")).toFile();
+    private FSResources() {
         
     }
-
-    @Override
-    public Filter loadFilter(InputStream filterFileContents) throws IOException {
-        if ( filterFileContents == null )
-            return null;
-        return MOCK_FILTER;
-    }
-
 }
diff --git a/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/impl/FSWorkspaceProject.java b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/impl/FSWorkspaceProject.java
index 424b2ea..a15385d 100644
--- a/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/impl/FSWorkspaceProject.java
+++ b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/impl/FSWorkspaceProject.java
@@ -69,7 +69,7 @@ public class FSWorkspaceProject extends FSWorkspaceResource implements Workspace
 
     @Override
     public Filter getFilter() throws IOException {
-        File filterFile = filterLocator.findFilterLocation(syncRoot);
+        File filterFile = filterLocator.findFilterLocation(new File(syncRoot, "jcr_root"));
         if ( filterFile == null || !filterFile.exists() )
             return null;
         
diff --git a/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/package-info.java b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/package-info.java
new file mode 100644
index 0000000..56c177b
--- /dev/null
+++ b/shared/modules/sync-fs/src/main/java/org/apache/sling/ide/content/sync/fs/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.sling.ide.content.sync.fs;
\ No newline at end of file
diff --git a/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java b/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
index 85a935c..6b35f08 100644
--- a/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
+++ b/shared/modules/sync-fs/src/test/java/org/apache/sling/ide/content/sync/fs/impl/MockFilterLocator.java
@@ -38,7 +38,7 @@ public class MockFilterLocator implements FilterLocator {
     @Override
     public File findFilterLocation(File syncDirectory) {
         
-        return syncDirectory.toPath().
+        return syncDirectory.getParentFile().toPath().
                 resolve(Paths.get("META-INF", "vault", "filter.xml")).toFile();
         
     }

-- 
To stop receiving notification emails like this one, please contact
rombert@apache.org.