/*
* Copyright 2016 JBoss by Red Hat.
*
* Licensed 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.jboss.as.repository;
import static org.jboss.as.repository.ContentFilter.Factory.createFileFilter;
import static org.jboss.as.repository.PathUtil.deleteRecursively;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.jboss.as.protocol.StreamUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for PathUtil.
* @author Emmanuel Hugonnet (c) 2016 Red Hat, inc.
*/
public class PathUtilTest {
private final Path root = new File("target", "temp").toPath().resolve("pathutil");
ContentFilter ALL = new ContentFilter() {
@Override
public boolean acceptFile(Path rootPath, Path file) throws IOException {
return true;
}
@Override
public boolean acceptFile(Path rootPath, Path file, InputStream in) throws IOException {
return true;
}
@Override
public boolean acceptDirectory(Path rootPath, Path dir) throws IOException {
return true;
}
};
public PathUtilTest() {
}
@Before
public void createRepository() throws IOException {
if (Files.exists(root)) {
deleteRecursively(root);
}
Files.createDirectories(root);
}
@After
public void destroyRepository() throws IOException {
deleteRecursively(root);
}
/**
* Test of resolveSecurely method, of class PathUtil.
*/
@Test
public void testResolveSecurely() throws Exception {
Path result = PathUtil.resolveSecurely(root, "../pathutil/test");
Assert.assertEquals(root.resolve("test"), result);
try {
PathUtil.resolveSecurely(root, "../test");
Assert.fail("We shouldn't be able to go out");
} catch (IllegalArgumentException ioex) {
Assert.assertTrue(ioex.getMessage().contains("WFLYDR0013"));
}
try {
PathUtil.resolveSecurely(root, "test/../../test");
Assert.fail("We shouldn't be able to go out");
} catch (IllegalArgumentException ioex) {
Assert.assertTrue(ioex.getMessage().contains("WFLYDR0013"));
}
result = PathUtil.resolveSecurely(root, "/index.html");
Assert.assertEquals(root.resolve("index.html"), result);
result = PathUtil.resolveSecurely(root, "///index.html");
Assert.assertEquals(root.resolve("index.html"), result);
}
/**
* Test of isArchive method, of class PathUtil.
*/
@Test
public void testIsArchive() throws Exception {
Path archive = root.resolve("test.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
Path simpleFile = root.resolve("overlay.zip");
Files.copy(this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml"), simpleFile);
Assert.assertTrue(PathUtil.isArchive(archive));
Assert.assertFalse(PathUtil.isArchive(root));
Assert.assertFalse(PathUtil.isArchive(simpleFile));
}
/**
* Test of isArchive method, of class PathUtil.
*/
@Test
public void testReadFile() throws Exception {
Path archive = root.resolve("test.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
entry = new ZipEntry("single/test/test.html");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
String content = readFileContent(in);
Assert.assertEquals(readFileContent(PathUtil.readFile(archive.resolve("overlay.xhtml"), root)), content);
Assert.assertEquals(readFileContent(PathUtil.readFile(archive.resolve("single/test/test.html"), root)), content);
}
try {
readFileContent(PathUtil.readFile(archive.resolve("single/test.html"), root));
Assert.fail("Shouldn't find a file at " + archive.resolve("single/test.html"));
} catch (FileNotFoundException ex) {
}
}
private String readFileContent(Path path) throws Exception {
byte[] bytes = Files.readAllBytes(path);
return new String(bytes, "UTF-8");
}
private String readFileContent(InputStream in) throws Exception {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
byte[] buffer = new byte[8];
int length = 8;
while ((length = in.read(buffer, 0, length)) > 0) {
out.write(buffer, 0, length);
}
return out.toString("UTF-8");
}
}
/**
* Test of listFiles method, of class PathUtil.
*/
@Test
public void testListFiles() throws Exception {
Path archive = root.resolve("test.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
Files.createDirectory(root.resolve("zip"));
archive = root.resolve("zip").resolve("test.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
Files.copy(this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml"), root.resolve("overlay.xhtml"));
Files.createDirectories(root.resolve("empty").resolve("directory"));
Files.createDirectories(root.resolve("htdocs").resolve("www"));
Files.copy(this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml"), root.resolve("htdocs").resolve("www").resolve("overlay.xhtml"));
List<String> result = PathUtil.listFiles(root, root, ALL).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(9, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test.zip"));
Assert.assertTrue(result.contains("zip/"));
Assert.assertTrue(result.contains("empty/directory/"));
Assert.assertTrue(result.contains("empty/"));
Assert.assertTrue(result.contains("htdocs/www/overlay.xhtml"));
Assert.assertTrue(result.contains("htdocs/www/"));
Assert.assertTrue(result.contains("htdocs/"));
result = PathUtil.listFiles(root, root, explodableFileFilter(true)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test.zip"));
result = PathUtil.listFiles(root, root, directoryListFileFilter()).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
result = PathUtil.listFiles(root, root, ContentFilter.Factory.createContentFilter(2, true)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test.zip"));
result = PathUtil.listFiles(root, root, ContentFilter.Factory.createContentFilter(2, false)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(8, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/"));
Assert.assertTrue(result.contains("zip/test.zip"));
Assert.assertTrue(result.contains("empty/"));
Assert.assertTrue(result.contains("empty/directory/"));
Assert.assertTrue(result.contains("htdocs/www/"));
Assert.assertTrue(result.contains("htdocs/"));
result = PathUtil.listFiles(root, root, ContentFilter.Factory.createContentFilter(3, false)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(9, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/"));
Assert.assertTrue(result.contains("zip/test.zip"));
Assert.assertTrue(result.contains("empty/"));
Assert.assertTrue(result.contains("empty/directory/"));
Assert.assertTrue(result.contains("htdocs/"));
Assert.assertTrue(result.contains("htdocs/www/"));
Assert.assertTrue(result.contains("htdocs/www/overlay.xhtml"));
}
/**
* Test of listFiles method, of class PathUtil.
*/
@Test
public void testListFileInArchives() throws Exception {
Path archive = root.resolve("test.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
Path unexploded = Files.createDirectory(root.resolve("unexploded")).resolve("unexploded.zip");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(unexploded))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
entry = new ZipEntry("test.zip");
out.putNextEntry(entry);
try (InputStream in = Files.newInputStream(root.resolve("test.zip"))) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
entry = new ZipEntry("zip/test2.zip");
out.putNextEntry(entry);
try (InputStream in = Files.newInputStream(root.resolve("test.zip"))) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
Files.delete(archive);
List<String> result = PathUtil.listFiles(unexploded, root, ALL).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(3, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test2.zip"));
result = PathUtil.listFiles(unexploded, root, explodableFileFilter(true)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test2.zip"));
result = PathUtil.listFiles(unexploded, root, directoryListFileFilter()).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
result = PathUtil.listFiles(unexploded, root, ContentFilter.Factory.createContentFilter(2, true)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test2.zip"));
result = PathUtil.listFiles(unexploded, root, ContentFilter.Factory.createContentFilter(2, false)).stream().map(ContentRepositoryElement::getPath).collect(Collectors.toList());
Assert.assertEquals(3, result.size());
Assert.assertTrue(result.contains("overlay.xhtml"));
Assert.assertTrue(result.contains("test.zip"));
Assert.assertTrue(result.contains("zip/test2.zip"));
}
/**
* Test of createTempDirectory method, of class PathUtil.
*/
@Test
public void testCreateTempDirectory() throws Exception {
Path result = PathUtil.createTempDirectory(root, "test");
Assert.assertTrue(Files.exists(result));
Assert.assertTrue(Files.isDirectory(result));
Assert.assertTrue(result.getFileName().toString().startsWith("test"));
}
/**
* Test of unzip method, of class PathUtil.
*/
@Test
public void testUnzip() throws Exception {
Path archive = root.resolve("test.zip");
Path target = root.resolve("target");
try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(archive))) {
ZipEntry entry = new ZipEntry("overlay.xhtml");
out.putNextEntry(entry);
try (InputStream in = this.getClass().getClassLoader().getResourceAsStream("overlay.xhtml")) {
StreamUtils.copyStream(in, out);
}
out.closeEntry();
}
PathUtil.unzip(archive, target);
Assert.assertTrue(Files.exists(target));
Path explodedFile = target.resolve("overlay.xhtml");
Assert.assertTrue(Files.exists(explodedFile));
Assert.assertTrue(Files.isRegularFile(explodedFile));
}
private static ContentFilter explodableFileFilter(boolean archiveOnly) {
return createFileFilter(-1, archiveOnly);
}
private static ContentFilter directoryListFileFilter() {
return createFileFilter(1, false);
}
}