/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* 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 com.asakusafw.runtime.stage.launcher;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.Arrays;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
/**
* Base test class for this package.
*/
public abstract class LauncherTestRoot {
/**
* Temporary folder.
*/
@Rule
public final TemporaryFolder folder = new TemporaryFolder();
/**
* assert the target resource is in any jar files.
* @param urls jar file URLs
* @param resourceName the target resource name
*/
public void assertClasspath(final URL[] urls, String resourceName) {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
ClassLoader loader = new URLClassLoader(urls);
try {
assertThat(loader.getResource(resourceName), is(notNullValue()));
} finally {
if (loader instanceof Closeable) {
try {
((Closeable) loader).close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
});
}
/**
* Returns a file matcher which file is in the URLs.
* assert the target resource is in any jar files.
* @param classLoader URL class loader
* @return the matcher
*/
public Matcher<File> inClasspath(ClassLoader classLoader) {
if (classLoader instanceof URLClassLoader) {
return inClasspath(((URLClassLoader) classLoader).getURLs());
}
throw new AssertionError(classLoader);
}
/**
* Returns a file matcher which file is in the URLs.
* assert the target resource is in any jar files.
* @param urls URLs
* @return the matcher
*/
public Matcher<File> inClasspath(URL[] urls) {
return new BaseMatcher<File>() {
@Override
public boolean matches(Object item) {
try {
File actual = ((File) item).getCanonicalFile();
for (URL url : urls) {
if (url.getProtocol().equalsIgnoreCase("file") == false) {
continue;
}
File expected = new File(url.toURI()).getCanonicalFile();
if (expected.equals(actual)) {
return true;
}
}
return false;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
@Override
public void describeTo(Description description) {
description.appendText("in classpath:").appendValue(Arrays.toString(urls));
}
};
}
/**
* Copy a resource file to temporary folder.
* @param path the resource file (obtain using {@link Class#getResource(String)})
* @return the copied file
* @throws IOException if failed to copy the target file
*/
public File putFile(String path) throws IOException {
return putFile(path, folder.newFile(new File(path).getName()));
}
private File putFile(String path, File target) throws FileNotFoundException, IOException {
assert target != null;
try (InputStream input = getClass().getResourceAsStream(path)) {
assertThat(path, input, is(notNullValue()));
prepareParent(target);
try (OutputStream output = new FileOutputStream(target)) {
copyStream(input, output);
}
}
return target;
}
private void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buf = new byte[512];
while (true) {
int read = input.read(buf);
if (read < 0) {
break;
}
output.write(buf, 0, read);
}
}
private void prepareParent(File target) throws IOException {
assert target != null;
if (target.getParentFile().isDirectory() == false && target.getParentFile().mkdirs() == false) {
throw new IOException(MessageFormat.format(
"Failed to copy into {0} (cannot create target directory)",
target));
}
}
}