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 <[email protected]> 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 [email protected].
