|  | 
| 16 | 16 | import java.io.File; | 
| 17 | 17 | import java.io.FileOutputStream; | 
| 18 | 18 | import java.io.IOException; | 
|  | 19 | +import java.io.OutputStream; | 
| 19 | 20 | import java.net.URI; | 
| 20 | 21 | import java.nio.file.DirectoryStream; | 
| 21 | 22 | import java.nio.file.FileSystem; | 
| 22 | 23 | import java.nio.file.FileSystems; | 
| 23 | 24 | import java.nio.file.Files; | 
| 24 | 25 | import java.nio.file.Path; | 
|  | 26 | +import java.nio.file.Paths; | 
|  | 27 | +import java.nio.file.StandardOpenOption; | 
| 25 | 28 | import java.util.HashMap; | 
| 26 | 29 | import java.util.Iterator; | 
|  | 30 | +import java.util.Objects; | 
| 27 | 31 | import java.util.Spliterator; | 
| 28 | 32 | import java.util.Spliterators; | 
| 29 | 33 | import java.util.concurrent.TimeUnit; | 
|  | 34 | +import java.util.stream.Stream; | 
| 30 | 35 | import java.util.stream.StreamSupport; | 
| 31 | 36 | 
 | 
| 32 | 37 | import org.apache.sshd.client.SshClient; | 
| @@ -91,6 +96,99 @@ public void testNodeIdFolder() throws Exception | 
| 91 | 96 |         assertThat(iterator.hasNext(), is(false)); | 
| 92 | 97 |     } | 
| 93 | 98 | 
 | 
|  | 99 | +    @Test | 
|  | 100 | +    public void testCopy() throws Exception | 
|  | 101 | +    { | 
|  | 102 | +        new File("target/testCopy/." + NodeFileSystemProvider.SCHEME + "/the-test/myhost/a").mkdirs(); | 
|  | 103 | + | 
|  | 104 | +        for (String classpathEntry : System.getProperty("java.class.path").split(File.pathSeparator)) | 
|  | 105 | +        { | 
|  | 106 | +            File cpFile = new File(classpathEntry); | 
|  | 107 | +            if (cpFile.isDirectory()) | 
|  | 108 | +                continue; | 
|  | 109 | +            copyFile(cpFile.toPath(), Paths.get("target/testCopy/.jco/the-test/myhost", cpFile.getName())); | 
|  | 110 | +        } | 
|  | 111 | + | 
|  | 112 | +        TestSshServer testSshServer = closer.register(new TestSshServer("target/testCopy")); | 
|  | 113 | +        SshClient sshClient = closer.register(SshClient.setUpDefaultClient()); | 
|  | 114 | +        sshClient.start(); | 
|  | 115 | +        closer.register(sshClient.connect(null, "localhost", testSshServer.getPort()) | 
|  | 116 | +            .verify(30, TimeUnit.SECONDS) | 
|  | 117 | +            .getSession()); | 
|  | 118 | + | 
|  | 119 | +        HashMap<String, Object> env = new HashMap<>(); | 
|  | 120 | +        env.put(NodeFileSystemProvider.IS_WINDOWS_ENV, IS_WINDOWS); | 
|  | 121 | +        env.put(NodeFileSystemProvider.SFTP_HOST_ENV, "localhost"); | 
|  | 122 | +        env.put(NodeFileSystemProvider.SFTP_PORT_ENV, testSshServer.getPort()); | 
|  | 123 | +        env.put(NodeFileSystemProvider.SFTP_USERNAME_ENV, System.getProperty("user.name")); | 
|  | 124 | +        env.put(SshClient.class.getName(), sshClient); | 
|  | 125 | +        NodeFileSystem fileSystem = closer.register((NodeFileSystem)FileSystems.newFileSystem(URI.create(NodeFileSystemProvider.SCHEME + ":the-test/myhost!/." + NodeFileSystemProvider.SCHEME + "/the-test/myhost"), env)); | 
|  | 126 | + | 
|  | 127 | +        Path targetPath = Paths.get("target/testCopy-target/"); | 
|  | 128 | +        Files.createDirectories(targetPath); | 
|  | 129 | +        Path sourcePath = fileSystem.getPath("."); | 
|  | 130 | + | 
|  | 131 | +        copyDir(sourcePath, targetPath); | 
|  | 132 | +    } | 
|  | 133 | + | 
|  | 134 | +    public static void copyDir(Path srcDir, Path destDir) throws IOException | 
|  | 135 | +    { | 
|  | 136 | +        if (!Files.isDirectory(Objects.requireNonNull(srcDir))) | 
|  | 137 | +            throw new IllegalArgumentException("Source is not a directory: " + srcDir); | 
|  | 138 | +        Objects.requireNonNull(destDir); | 
|  | 139 | +        if (Files.exists(destDir) && !Files.isDirectory(destDir)) | 
|  | 140 | +            throw new IllegalArgumentException("Destination is not a directory: " + destDir); | 
|  | 141 | +        else if (!Files.exists(destDir)) | 
|  | 142 | +            Files.createDirectory(destDir); // only attempt top create 1 level of directory (parent must exist) | 
|  | 143 | + | 
|  | 144 | +        try (Stream<Path> sourceStream = Files.walk(srcDir)) | 
|  | 145 | +        { | 
|  | 146 | +            Iterator<Path> iterFiles = sourceStream | 
|  | 147 | +                .filter(Files::isRegularFile) | 
|  | 148 | +                .iterator(); | 
|  | 149 | +            while (iterFiles.hasNext()) | 
|  | 150 | +            { | 
|  | 151 | +                Path sourceFile = iterFiles.next(); | 
|  | 152 | +                Path relative = srcDir.relativize(sourceFile); | 
|  | 153 | +                Path destFile = resolvePath(destDir, relative); | 
|  | 154 | +                if (!Files.exists(destFile.getParent())) | 
|  | 155 | +                    Files.createDirectories(destFile.getParent()); | 
|  | 156 | +                copyFile(sourceFile, destFile); | 
|  | 157 | +            } | 
|  | 158 | +        } | 
|  | 159 | +    } | 
|  | 160 | + | 
|  | 161 | +    public static void copyFile(Path srcFile, Path destFile) throws IOException | 
|  | 162 | +    { | 
|  | 163 | +        if (!Files.isRegularFile(Objects.requireNonNull(srcFile))) | 
|  | 164 | +            throw new IllegalArgumentException("Source is not a file: " + srcFile); | 
|  | 165 | +        Objects.requireNonNull(destFile); | 
|  | 166 | + | 
|  | 167 | +        try (OutputStream out = Files.newOutputStream(destFile, | 
|  | 168 | +            StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) | 
|  | 169 | +        { | 
|  | 170 | +            Files.copy(srcFile, out); | 
|  | 171 | +        } | 
|  | 172 | +    } | 
|  | 173 | +     | 
|  | 174 | +    public static Path resolvePath(Path basePath, Path relative) | 
|  | 175 | +    { | 
|  | 176 | +        if (relative.isAbsolute()) | 
|  | 177 | +            throw new IllegalArgumentException("Relative path cannot be absolute"); | 
|  | 178 | + | 
|  | 179 | +        if (basePath.getFileSystem().equals(relative.getFileSystem())) | 
|  | 180 | +        { | 
|  | 181 | +            return basePath.resolve(relative); | 
|  | 182 | +        } | 
|  | 183 | +        else | 
|  | 184 | +        { | 
|  | 185 | +            for (Path segment : relative) | 
|  | 186 | +                basePath = basePath.resolve(segment.toString()); | 
|  | 187 | +            return basePath; | 
|  | 188 | +        } | 
|  | 189 | +    } | 
|  | 190 | + | 
|  | 191 | + | 
| 94 | 192 |     @Test | 
| 95 | 193 |     public void testHomeFolderIsDefault() throws Exception | 
| 96 | 194 |     { | 
|  | 
0 commit comments