+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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);
- }
- }
-}
--- /dev/null
+<?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>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?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>
--- /dev/null
+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
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+Main-Class: org.argeo.sync.cli.Sync
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
+additional.bundles = org.apache.sshd.common,\
+ org.slf4j.log4j12,\
+ org.slf4j.api,\
+ org.apache.sshd.core
--- /dev/null
+/tomcat-jni-*.jar
--- /dev/null
+<?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
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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();
+
+ }
+ }
+
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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);
+ }
+ }
+}
--- /dev/null
+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;
+ }
+}
<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>