Introduce Argeo Sync
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 12 Mar 2019 15:46:03 +0000 (16:46 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 12 Mar 2019 15:46:03 +0000 (16:46 +0100)
18 files changed:
org.argeo.cms/src/org/argeo/cms/cmd/Sync.java [deleted file]
org.argeo.cms/src/org/argeo/cms/cmd/SyncFileVisitor.java [deleted file]
org.argeo.maintenance/src/org/argeo/maintenance/backup/SshSync.java [deleted file]
org.argeo.sync/.classpath [new file with mode: 0644]
org.argeo.sync/.gitignore [new file with mode: 0644]
org.argeo.sync/.project [new file with mode: 0644]
org.argeo.sync/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
org.argeo.sync/META-INF/.gitignore [new file with mode: 0644]
org.argeo.sync/bnd.bnd [new file with mode: 0644]
org.argeo.sync/build.properties [new file with mode: 0644]
org.argeo.sync/lib/.gitignore [new file with mode: 0644]
org.argeo.sync/pom.xml [new file with mode: 0644]
org.argeo.sync/src/org/argeo/sync/SyncException.java [new file with mode: 0644]
org.argeo.sync/src/org/argeo/sync/cli/Sync.java [new file with mode: 0644]
org.argeo.sync/src/org/argeo/sync/fs/PathSync.java [new file with mode: 0644]
org.argeo.sync/src/org/argeo/sync/fs/SshSync.java [new file with mode: 0644]
org.argeo.sync/src/org/argeo/sync/fs/SyncFileVisitor.java [new file with mode: 0644]
pom.xml

diff --git a/org.argeo.cms/src/org/argeo/cms/cmd/Sync.java b/org.argeo.cms/src/org/argeo/cms/cmd/Sync.java
deleted file mode 100644 (file)
index 515ef6c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.argeo.cms.cmd;
-
-import java.net.URI;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.spi.FileSystemProvider;
-import java.time.ZonedDateTime;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.CmsException;
-import org.argeo.jackrabbit.fs.DavexFsProvider;
-import org.argeo.util.LangUtils;
-
-public class Sync {
-       private final static Log log = LogFactory.getLog(Sync.class);
-
-       public static void main(String args[]) {
-               Map<String, String> arguments = new HashMap<>();
-               boolean skipNext = false;
-               String currValue = null;
-               for (int i = 0; i < args.length; i++) {
-                       if (skipNext) {
-                               skipNext = false;
-                               currValue = null;
-                               continue;
-                       }
-                       String arg = args[i];
-                       if (arg.startsWith("-")) {
-                               if (i + 1 < args.length) {
-                                       if (!args[i + 1].startsWith("-")) {
-                                               currValue = args[i + 1];
-                                               skipNext = true;
-                                       }
-                               }
-                               arguments.put(arg, currValue);
-                       } else {
-                               // TODO add multiple?
-                       }
-               }
-
-               try {
-                       URI sourceUri = new URI(arguments.get("-i"));
-                       URI targetUri = new URI(arguments.get("-o"));
-                       FileSystemProvider sourceFsProvider = createFsProvider(sourceUri);
-                       FileSystemProvider targetFsProvider = createFsProvider(targetUri);
-                       Path sourceBasePath = sourceFsProvider.getPath(sourceUri);
-                       Path targetBasePath = targetFsProvider.getPath(targetUri);
-                       SyncFileVisitor syncFileVisitor = new SyncFileVisitor(sourceBasePath, targetBasePath);
-                       ZonedDateTime begin = ZonedDateTime.now();
-                       Files.walkFileTree(sourceBasePath, syncFileVisitor);
-                       if (log.isDebugEnabled())
-                               log.debug("Sync from " + sourceBasePath + " to " + targetBasePath + " took " + LangUtils.since(begin));
-               } catch (Exception e) {
-                       e.printStackTrace();
-               }
-       }
-
-       private static FileSystemProvider createFsProvider(URI uri) {
-               FileSystemProvider fsProvider;
-               if (uri.getScheme().equals("file"))
-                       fsProvider = FileSystems.getDefault().provider();
-               else if (uri.getScheme().equals("davex"))
-                       fsProvider = new DavexFsProvider();
-               else
-                       throw new CmsException("URI scheme not supported for " + uri);
-               return fsProvider;
-       }
-
-       static enum Arg {
-               to, from;
-       }
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/cmd/SyncFileVisitor.java b/org.argeo.cms/src/org/argeo/cms/cmd/SyncFileVisitor.java
deleted file mode 100644 (file)
index 6ec75f4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.argeo.cms.cmd;
-
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/** Synchronises two directory structures. */
-public class SyncFileVisitor extends SimpleFileVisitor<Path> {
-       private final static Log log = LogFactory.getLog(SyncFileVisitor.class);
-
-       private final Path sourceBasePath;
-       private final Path targetBasePath;
-
-       public SyncFileVisitor(Path sourceBasePath, Path targetBasePath) {
-               this.sourceBasePath = sourceBasePath;
-               this.targetBasePath = targetBasePath;
-       }
-
-       @Override
-       public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
-               Path targetPath = toTargetPath(dir);
-               Files.createDirectories(targetPath);
-               return FileVisitResult.CONTINUE;
-       }
-
-       @Override
-       public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-               Path targetPath = toTargetPath(file);
-               try {
-                       Files.copy(file, targetPath);
-                       if (log.isDebugEnabled())
-                               log.debug("Copied " + targetPath);
-               } catch (Exception e) {
-                       log.error("Cannot copy " + file + " to " + targetPath, e);
-               }
-               return FileVisitResult.CONTINUE;
-       }
-
-       @Override
-       public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
-               log.error("Cannot sync " + file, exc);
-               return FileVisitResult.CONTINUE;
-       }
-
-       private Path toTargetPath(Path sourcePath) {
-               Path relativePath = sourceBasePath.relativize(sourcePath);
-               Path targetPath = targetBasePath.resolve(relativePath.toString());
-               return targetPath;
-       }
-}
diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/SshSync.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/SshSync.java
deleted file mode 100644 (file)
index 618e227..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.argeo.maintenance.backup;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.channel.ClientChannel;
-import org.apache.sshd.client.channel.ClientChannelEvent;
-import org.apache.sshd.client.future.ConnectFuture;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.subsystem.sftp.SftpFileSystem;
-import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseOutputStream;
-
-public class SshSync {
-       private final static Log log = LogFactory.getLog(SshSync.class);
-       
-       public static void main(String[] args) {
-
-               String login = System.getProperty("user.name");
-               Scanner s = new Scanner(System.in);
-               String password = s.next();
-               String host = "localhost";
-               int port = 22;
-
-               try (SshClient client = SshClient.setUpDefaultClient()) {
-                       client.start();
-
-//                     SimpleClient simpleClient= AbstractSimpleClientSessionCreator.wrap(client, null);
-//                     simpleClient.sessionLogin(host, login, password);
-
-                       ConnectFuture connectFuture = client.connect(login, host, port);
-                       connectFuture.await();
-                       ClientSession session = connectFuture.getSession();
-
-                       try {
-
-                               session.addPasswordIdentity(new String(password));
-                               session.auth().verify(1000l);
-
-                               SftpFileSystemProvider fsProvider = new SftpFileSystemProvider(client);
-
-                               SftpFileSystem fs = fsProvider.newFileSystem(session);
-                               Path testPath = fs.getPath("/home/" + login + "/tmp");
-                               Files.list(testPath).forEach(System.out::println);
-                               test(testPath);
-
-                       } finally {
-                               client.stop();
-                       }
-               } catch (Exception e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
-       }
-       
-       static void test(Path testBase) {
-               try {
-                       Path testPath = testBase.resolve("ssh-test.txt");
-                       Files.createFile(testPath);
-                       log.debug("Created file " + testPath);
-                       Files.delete(testPath);
-                       log.debug("Deleted " + testPath);
-                       String txt = "TEST\nTEST2\n";
-                       byte[] arr = txt.getBytes();
-                       Files.write(testPath, arr);
-                       log.debug("Wrote " + testPath);
-                       byte[] read = Files.readAllBytes(testPath);
-                       log.debug("Read " + testPath);
-                       Path testDir = testBase.resolve("testDir");
-                       log.debug("Resolved " + testDir);
-                       // Copy
-                       Files.createDirectory(testDir);
-                       log.debug("Created directory " + testDir);
-                       Path subsubdir = Files.createDirectories(testDir.resolve("subdir/subsubdir"));
-                       log.debug("Created sub directories " + subsubdir);
-                       Path copiedFile = testDir.resolve("copiedFile.txt");
-                       log.debug("Resolved " + copiedFile);
-                       Path relativeCopiedFile = testDir.relativize(copiedFile);
-                       log.debug("Relative copied file " + relativeCopiedFile);
-                       try (OutputStream out = Files.newOutputStream(copiedFile); InputStream in = Files.newInputStream(testPath)) {
-                               IOUtils.copy(in, out);
-                       }
-                       log.debug("Copied " + testPath + " to " + copiedFile);
-                       Files.delete(testPath);
-                       log.debug("Deleted " + testPath);
-                       byte[] copiedRead = Files.readAllBytes(copiedFile);
-                       log.debug("Read " + copiedFile);
-                       // Browse directories
-                       DirectoryStream<Path> files = Files.newDirectoryStream(testDir);
-                       int fileCount = 0;
-                       Path listedFile = null;
-                       for (Path file : files) {
-                               fileCount++;
-                               if (!Files.isDirectory(file))
-                                       listedFile = file;
-                       }
-                       log.debug("Listed " + testDir);
-                       // Generic attributes
-                       Map<String, Object> attrs = Files.readAttributes(copiedFile, "*");
-                       log.debug("Read attributes of " + copiedFile + ": " + attrs.keySet());
-               } catch (IOException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
-
-       }
-       
-       static void openShell(ClientSession session) {
-               try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
-                       channel.setIn(new NoCloseInputStream(System.in));
-                       channel.setOut(new NoCloseOutputStream(System.out));
-                       channel.setErr(new NoCloseOutputStream(System.err));
-                       channel.open();
-
-                       Set<ClientChannelEvent> events = new HashSet<>();
-                       events.add(ClientChannelEvent.CLOSED);
-                       channel.waitFor(events, 0);
-               } catch (IOException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               } finally {
-                       session.close(false);
-               }
-       }
-}
diff --git a/org.argeo.sync/.classpath b/org.argeo.sync/.classpath
new file mode 100644 (file)
index 0000000..a7acb82
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="lib" path="lib/tomcat-jni-9.0.16.jar"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.argeo.sync/.gitignore b/org.argeo.sync/.gitignore
new file mode 100644 (file)
index 0000000..09e3bc9
--- /dev/null
@@ -0,0 +1,2 @@
+/bin/
+/target/
diff --git a/org.argeo.sync/.project b/org.argeo.sync/.project
new file mode 100644 (file)
index 0000000..38af869
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.sync</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/org.argeo.sync/.settings/org.eclipse.jdt.core.prefs b/org.argeo.sync/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..7e2e119
--- /dev/null
@@ -0,0 +1,101 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
diff --git a/org.argeo.sync/META-INF/.gitignore b/org.argeo.sync/META-INF/.gitignore
new file mode 100644 (file)
index 0000000..4854a41
--- /dev/null
@@ -0,0 +1 @@
+/MANIFEST.MF
diff --git a/org.argeo.sync/bnd.bnd b/org.argeo.sync/bnd.bnd
new file mode 100644 (file)
index 0000000..3ae5c17
--- /dev/null
@@ -0,0 +1 @@
+Main-Class: org.argeo.sync.cli.Sync
diff --git a/org.argeo.sync/build.properties b/org.argeo.sync/build.properties
new file mode 100644 (file)
index 0000000..f3e2c2c
--- /dev/null
@@ -0,0 +1,8 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
+additional.bundles = org.apache.sshd.common,\
+                     org.slf4j.log4j12,\
+                     org.slf4j.api,\
+                     org.apache.sshd.core
diff --git a/org.argeo.sync/lib/.gitignore b/org.argeo.sync/lib/.gitignore
new file mode 100644 (file)
index 0000000..2142dc1
--- /dev/null
@@ -0,0 +1 @@
+/tomcat-jni-*.jar
diff --git a/org.argeo.sync/pom.xml b/org.argeo.sync/pom.xml
new file mode 100644 (file)
index 0000000..4e07d43
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.commons</groupId>
+               <artifactId>argeo-commons</artifactId>
+               <version>2.1.77-SNAPSHOT</version>
+               <relativePath>..</relativePath>
+       </parent>
+       <artifactId>org.argeo.sync</artifactId>
+       <name>Commons Sync Utility</name>
+       <dependencies>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.util</artifactId>
+                       <version>2.1.77-SNAPSHOT</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.jcr</artifactId>
+                       <version>2.1.77-SNAPSHOT</version>
+               </dependency>
+       </dependencies>
+</project>
\ No newline at end of file
diff --git a/org.argeo.sync/src/org/argeo/sync/SyncException.java b/org.argeo.sync/src/org/argeo/sync/SyncException.java
new file mode 100644 (file)
index 0000000..89bf869
--- /dev/null
@@ -0,0 +1,18 @@
+package org.argeo.sync;
+
+/** Commons exception for sync */
+public class SyncException extends RuntimeException {
+       private static final long serialVersionUID = -3371314343580218538L;
+
+       public SyncException(String message) {
+               super(message);
+       }
+
+       public SyncException(String message, Throwable cause) {
+               super(message, cause);
+       }
+
+       public SyncException(Object source, Object target, Throwable cause) {
+               super("Cannot sync from " + source + " to " + target, cause);
+       }
+}
diff --git a/org.argeo.sync/src/org/argeo/sync/cli/Sync.java b/org.argeo.sync/src/org/argeo/sync/cli/Sync.java
new file mode 100644 (file)
index 0000000..6bb098b
--- /dev/null
@@ -0,0 +1,35 @@
+package org.argeo.sync.cli;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.argeo.sync.fs.PathSync;
+
+public class Sync {
+
+       public static void main(String[] args) {
+               Options options = new Options();
+               options.addOption("r", "recursive", false, "recurse into directories");
+               options.addOption(Option.builder().longOpt("progress").hasArg(false).desc("").build());
+
+               CommandLineParser parser = new DefaultParser();
+               try {
+                       CommandLine line = parser.parse(options, args);
+                       List<String> remaining = line.getArgList();
+
+                       URI sourceUri = new URI(remaining.get(0));
+                       URI targetUri = new URI(remaining.get(1));
+                       PathSync pathSync = new PathSync(sourceUri, targetUri);
+                       pathSync.run();
+               } catch (Exception exp) {
+                       exp.printStackTrace();
+
+               }
+       }
+
+}
diff --git a/org.argeo.sync/src/org/argeo/sync/fs/PathSync.java b/org.argeo.sync/src/org/argeo/sync/fs/PathSync.java
new file mode 100644 (file)
index 0000000..1dc30db
--- /dev/null
@@ -0,0 +1,60 @@
+package org.argeo.sync.fs;
+
+import java.net.URI;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.spi.FileSystemProvider;
+import java.time.ZonedDateTime;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jackrabbit.fs.DavexFsProvider;
+import org.argeo.sync.SyncException;
+import org.argeo.util.LangUtils;
+
+public class PathSync implements Runnable {
+       private final static Log log = LogFactory.getLog(PathSync.class);
+
+       private final URI sourceUri, targetUri;
+
+       public PathSync(URI sourceUri, URI targetUri) {
+               this.sourceUri = sourceUri;
+               this.targetUri = targetUri;
+       }
+
+       @Override
+       public void run() {
+               try {
+                       FileSystemProvider sourceFsProvider = createFsProvider(sourceUri);
+                       FileSystemProvider targetFsProvider = createFsProvider(targetUri);
+                       Path sourceBasePath = sourceUri.getScheme() != null ? sourceFsProvider.getPath(sourceUri)
+                                       : Paths.get(sourceUri.getPath());
+                       Path targetBasePath = targetUri.getScheme() != null ? targetFsProvider.getPath(targetUri)
+                                       : Paths.get(targetUri.getPath());
+                       SyncFileVisitor syncFileVisitor = new SyncFileVisitor(sourceBasePath, targetBasePath);
+                       ZonedDateTime begin = ZonedDateTime.now();
+                       Files.walkFileTree(sourceBasePath, syncFileVisitor);
+                       if (log.isDebugEnabled())
+                               log.debug("Sync from " + sourceBasePath + " to " + targetBasePath + " took " + LangUtils.since(begin));
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+
+       private static FileSystemProvider createFsProvider(URI uri) {
+               FileSystemProvider fsProvider;
+               if (uri.getScheme() == null || uri.getScheme().equals("file"))
+                       fsProvider = FileSystems.getDefault().provider();
+               else if (uri.getScheme().equals("davex"))
+                       fsProvider = new DavexFsProvider();
+               else
+                       throw new SyncException("URI scheme not supported for " + uri);
+               return fsProvider;
+       }
+
+       static enum Arg {
+               to, from;
+       }
+}
diff --git a/org.argeo.sync/src/org/argeo/sync/fs/SshSync.java b/org.argeo.sync/src/org/argeo/sync/fs/SshSync.java
new file mode 100644 (file)
index 0000000..e89ba85
--- /dev/null
@@ -0,0 +1,153 @@
+package org.argeo.sync.fs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.PublicKey;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.sshd.agent.SshAgent;
+import org.apache.sshd.agent.unix.UnixAgentFactory;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.channel.ClientChannelEvent;
+import org.apache.sshd.client.future.ConnectFuture;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.client.subsystem.sftp.SftpFileSystem;
+import org.apache.sshd.client.subsystem.sftp.SftpFileSystemProvider;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.apache.sshd.common.util.io.NoCloseOutputStream;
+
+public class SshSync {
+       private final static Log log = LogFactory.getLog(SshSync.class);
+
+       public static void main(String[] args) {
+
+
+               try (SshClient client = SshClient.setUpDefaultClient()) {
+                       client.start();
+
+                       UnixAgentFactory agentFactory = new UnixAgentFactory();
+                       client.setAgentFactory(agentFactory);
+//                     SshAgent sshAgent = agentFactory.createClient(client);
+//                     List<? extends Map.Entry<PublicKey, String>> identities = sshAgent.getIdentities();
+//                     for (Map.Entry<PublicKey, String> entry : identities) {
+//                             System.out.println(entry.getValue() + " : " + entry.getKey());
+//                     }
+
+                       
+                       String login = System.getProperty("user.name");
+//                     Scanner s = new Scanner(System.in);
+//                     String password = s.next();
+                       String host = "localhost";
+                       int port = 22;
+
+//                     SimpleClient simpleClient= AbstractSimpleClientSessionCreator.wrap(client, null);
+//                     simpleClient.sessionLogin(host, login, password);
+
+                       ConnectFuture connectFuture = client.connect(login, host, port);
+                       connectFuture.await();
+                       ClientSession session = connectFuture.getSession();
+
+                       try {
+
+//                             session.addPasswordIdentity(new String(password));
+                               session.auth().verify(1000l);
+
+                               SftpFileSystemProvider fsProvider = new SftpFileSystemProvider(client);
+
+                               SftpFileSystem fs = fsProvider.newFileSystem(session);
+                               Path testPath = fs.getPath("/home/" + login + "/tmp");
+                               Files.list(testPath).forEach(System.out::println);
+                               test(testPath);
+
+                       } finally {
+                               client.stop();
+                       }
+               } catch (Exception e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+       }
+
+       static void test(Path testBase) {
+               try {
+                       Path testPath = testBase.resolve("ssh-test.txt");
+                       Files.createFile(testPath);
+                       log.debug("Created file " + testPath);
+                       Files.delete(testPath);
+                       log.debug("Deleted " + testPath);
+                       String txt = "TEST\nTEST2\n";
+                       byte[] arr = txt.getBytes();
+                       Files.write(testPath, arr);
+                       log.debug("Wrote " + testPath);
+                       byte[] read = Files.readAllBytes(testPath);
+                       log.debug("Read " + testPath);
+                       Path testDir = testBase.resolve("testDir");
+                       log.debug("Resolved " + testDir);
+                       // Copy
+                       Files.createDirectory(testDir);
+                       log.debug("Created directory " + testDir);
+                       Path subsubdir = Files.createDirectories(testDir.resolve("subdir/subsubdir"));
+                       log.debug("Created sub directories " + subsubdir);
+                       Path copiedFile = testDir.resolve("copiedFile.txt");
+                       log.debug("Resolved " + copiedFile);
+                       Path relativeCopiedFile = testDir.relativize(copiedFile);
+                       log.debug("Relative copied file " + relativeCopiedFile);
+                       try (OutputStream out = Files.newOutputStream(copiedFile);
+                                       InputStream in = Files.newInputStream(testPath)) {
+                               IOUtils.copy(in, out);
+                       }
+                       log.debug("Copied " + testPath + " to " + copiedFile);
+                       Files.delete(testPath);
+                       log.debug("Deleted " + testPath);
+                       byte[] copiedRead = Files.readAllBytes(copiedFile);
+                       log.debug("Read " + copiedFile);
+                       // Browse directories
+                       DirectoryStream<Path> files = Files.newDirectoryStream(testDir);
+                       int fileCount = 0;
+                       Path listedFile = null;
+                       for (Path file : files) {
+                               fileCount++;
+                               if (!Files.isDirectory(file))
+                                       listedFile = file;
+                       }
+                       log.debug("Listed " + testDir);
+                       // Generic attributes
+                       Map<String, Object> attrs = Files.readAttributes(copiedFile, "*");
+                       log.debug("Read attributes of " + copiedFile + ": " + attrs.keySet());
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+
+       }
+
+       static void openShell(ClientSession session) {
+               try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
+                       channel.setIn(new NoCloseInputStream(System.in));
+                       channel.setOut(new NoCloseOutputStream(System.out));
+                       channel.setErr(new NoCloseOutputStream(System.err));
+                       channel.open();
+
+                       Set<ClientChannelEvent> events = new HashSet<>();
+                       events.add(ClientChannelEvent.CLOSED);
+                       channel.waitFor(events, 0);
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } finally {
+                       session.close(false);
+               }
+       }
+}
diff --git a/org.argeo.sync/src/org/argeo/sync/fs/SyncFileVisitor.java b/org.argeo.sync/src/org/argeo/sync/fs/SyncFileVisitor.java
new file mode 100644 (file)
index 0000000..de80320
--- /dev/null
@@ -0,0 +1,56 @@
+package org.argeo.sync.fs;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/** Synchronises two directory structures. */
+public class SyncFileVisitor extends SimpleFileVisitor<Path> {
+       private final static Log log = LogFactory.getLog(SyncFileVisitor.class);
+
+       private final Path sourceBasePath;
+       private final Path targetBasePath;
+
+       public SyncFileVisitor(Path sourceBasePath, Path targetBasePath) {
+               this.sourceBasePath = sourceBasePath;
+               this.targetBasePath = targetBasePath;
+       }
+
+       @Override
+       public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+               Path targetPath = toTargetPath(dir);
+               Files.createDirectories(targetPath);
+               return FileVisitResult.CONTINUE;
+       }
+
+       @Override
+       public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+               Path targetPath = toTargetPath(file);
+               try {
+                       Files.copy(file, targetPath);
+                       if (log.isDebugEnabled())
+                               log.debug("Copied " + targetPath);
+               } catch (Exception e) {
+                       log.error("Cannot copy " + file + " to " + targetPath, e);
+               }
+               return FileVisitResult.CONTINUE;
+       }
+
+       @Override
+       public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+               log.error("Cannot sync " + file, exc);
+               return FileVisitResult.CONTINUE;
+       }
+
+       private Path toTargetPath(Path sourcePath) {
+               Path relativePath = sourceBasePath.relativize(sourcePath);
+               Path targetPath = targetBasePath.resolve(relativePath.toString());
+               return targetPath;
+       }
+}
diff --git a/pom.xml b/pom.xml
index fb14ca6d4f9998e0bcde36d99e75bb480e828418..4efd8d8fc02c54109a8f5324ef38712b48e7874b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -22,6 +22,7 @@
                <module>org.argeo.util</module>
                <module>org.argeo.enterprise</module>
                <module>org.argeo.jcr</module>
+               <module>org.argeo.sync</module>
                <module>org.argeo.osgi.boot</module>
                <!-- Eclipse -->
                <module>org.argeo.eclipse.ui</module>