Move tools modules under spring-boot-tools
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
/**
|
||||
* Hamcrest matcher to tests that a byte array starts with specific bytes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ByteArrayStartsWith extends TypeSafeMatcher<byte[]> {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
public ByteArrayStartsWith(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("a byte array starting with ").appendValue(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(byte[] item) {
|
||||
if (item.length < bytes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (item[i] != bytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader;
|
||||
|
||||
import java.io.File;
|
||||
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.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.loader.Archive;
|
||||
import org.springframework.boot.loader.ExplodedArchive;
|
||||
import org.springframework.boot.loader.Archive.Entry;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ExplodedArchive}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ExplodedArchiveTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootFolder;
|
||||
|
||||
private ExplodedArchive archive;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
File file = this.temporaryFolder.newFile();
|
||||
TestJarCreator.createTestJar(file);
|
||||
|
||||
this.rootFolder = this.temporaryFolder.newFolder();
|
||||
JarFile jarFile = new JarFile(file);
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
File destination = new File(this.rootFolder.getAbsolutePath()
|
||||
+ File.separator + entry.getName());
|
||||
destination.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
destination.mkdir();
|
||||
}
|
||||
else {
|
||||
copy(jarFile.getInputStream(entry), new FileOutputStream(destination));
|
||||
}
|
||||
}
|
||||
this.archive = new ExplodedArchive(this.rootFolder);
|
||||
}
|
||||
|
||||
private void copy(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len = in.read(buffer);
|
||||
while (len != -1) {
|
||||
out.write(buffer, 0, len);
|
||||
len = in.read(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(this.archive.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Map<String, Archive.Entry> entries = getEntriesMap(this.archive);
|
||||
assertThat(entries.size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = this.archive.getUrl();
|
||||
assertThat(url, equalTo(this.rootFolder.toURI().toURL()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("nested.jar");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("jar:file:" + this.rootFolder.getPath() + "/nested.jar!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedDirArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("d/");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
Map<String, Entry> nestedEntries = getEntriesMap(nested);
|
||||
assertThat(nestedEntries.size(), equalTo(1));
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("file:" + this.rootFolder.getPath() + "/d/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredArchive() throws Exception {
|
||||
Archive filteredArchive = this.archive
|
||||
.getFilteredArchive(new Archive.EntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, Entry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return entryName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<String, Entry> entries = getEntriesMap(filteredArchive);
|
||||
assertThat(entries.size(), equalTo(1));
|
||||
URLClassLoader classLoader = new URLClassLoader(
|
||||
new URL[] { filteredArchive.getUrl() });
|
||||
assertThat(classLoader.getResourceAsStream("1.dat").read(), equalTo(1));
|
||||
assertThat(classLoader.getResourceAsStream("2.dat"), nullValue());
|
||||
}
|
||||
|
||||
private Map<String, Archive.Entry> getEntriesMap(Archive archive) {
|
||||
Map<String, Archive.Entry> entries = new HashMap<String, Archive.Entry>();
|
||||
for (Archive.Entry entry : archive.getEntries()) {
|
||||
entries.put(entry.getName(), entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.loader.Archive;
|
||||
import org.springframework.boot.loader.JarFileArchive;
|
||||
import org.springframework.boot.loader.Archive.Entry;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link JarFileArchive}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JarFileArchiveTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootJarFile;
|
||||
|
||||
private JarFileArchive archive;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.rootJarFile = this.temporaryFolder.newFile();
|
||||
TestJarCreator.createTestJar(this.rootJarFile);
|
||||
this.archive = new JarFileArchive(this.rootJarFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(this.archive.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Map<String, Archive.Entry> entries = getEntriesMap(this.archive);
|
||||
assertThat(entries.size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = this.archive.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedArchive() throws Exception {
|
||||
Entry entry = getEntriesMap(this.archive).get("nested.jar");
|
||||
Archive nested = this.archive.getNestedArchive(entry);
|
||||
assertThat(nested.getUrl().toString(),
|
||||
equalTo("jar:file:" + this.rootJarFile.getPath() + "!/nested.jar!/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredArchive() throws Exception {
|
||||
Archive filteredArchive = this.archive
|
||||
.getFilteredArchive(new Archive.EntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, Entry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return entryName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<String, Entry> entries = getEntriesMap(filteredArchive);
|
||||
assertThat(entries.size(), equalTo(1));
|
||||
}
|
||||
|
||||
private Map<String, Archive.Entry> getEntriesMap(Archive archive) {
|
||||
Map<String, Archive.Entry> entries = new HashMap<String, Archive.Entry>();
|
||||
for (Archive.Entry entry : archive.getEntries()) {
|
||||
entries.put(entry.getName(), entry);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/**
|
||||
* Creates a simple test jar.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class TestJarCreator {
|
||||
|
||||
public static void createTestJar(File file) throws Exception {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream);
|
||||
try {
|
||||
writeManifest(jarOutputStream, "j1");
|
||||
writeEntry(jarOutputStream, "1.dat", 1);
|
||||
writeEntry(jarOutputStream, "2.dat", 2);
|
||||
writeDirEntry(jarOutputStream, "d/");
|
||||
writeEntry(jarOutputStream, "d/9.dat", 9);
|
||||
|
||||
JarEntry nestedEntry = new JarEntry("nested.jar");
|
||||
byte[] nestedJarData = getNestedJarData();
|
||||
nestedEntry.setSize(nestedJarData.length);
|
||||
nestedEntry.setCompressedSize(nestedJarData.length);
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(nestedJarData);
|
||||
nestedEntry.setCrc(crc32.getValue());
|
||||
|
||||
nestedEntry.setMethod(ZipEntry.STORED);
|
||||
jarOutputStream.putNextEntry(nestedEntry);
|
||||
jarOutputStream.write(nestedJarData);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
finally {
|
||||
jarOutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getNestedJarData() throws Exception {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(byteArrayOutputStream);
|
||||
writeManifest(jarOutputStream, "j2");
|
||||
writeEntry(jarOutputStream, "3.dat", 3);
|
||||
writeEntry(jarOutputStream, "4.dat", 4);
|
||||
jarOutputStream.close();
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
private static void writeManifest(JarOutputStream jarOutputStream, String name)
|
||||
throws Exception {
|
||||
writeDirEntry(jarOutputStream, "META-INF/");
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Built-By", name);
|
||||
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
jarOutputStream.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
manifest.write(jarOutputStream);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private static void writeDirEntry(JarOutputStream jarOutputStream, String name)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private static void writeEntry(JarOutputStream jarOutputStream, String name, int data)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.write(new byte[] { (byte) data });
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader.data;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.loader.ByteArrayStartsWith;
|
||||
import org.springframework.boot.loader.data.RandomAccessData;
|
||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessDataFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataFileTests {
|
||||
|
||||
private static final byte[] BYTES;
|
||||
static {
|
||||
BYTES = new byte[256];
|
||||
for (int i = 0; i < BYTES.length; i++) {
|
||||
BYTES[i] = (byte) i;
|
||||
}
|
||||
}
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File tempFile;
|
||||
|
||||
private RandomAccessDataFile file;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.tempFile = temporaryFolder.newFile();
|
||||
FileOutputStream outputStream = new FileOutputStream(tempFile);
|
||||
outputStream.write(BYTES);
|
||||
outputStream.close();
|
||||
this.file = new RandomAccessDataFile(tempFile);
|
||||
this.inputStream = file.getInputStream();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() throws Exception {
|
||||
inputStream.close();
|
||||
file.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileNotNull() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must not be null");
|
||||
new RandomAccessDataFile(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileExists() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must exist");
|
||||
new RandomAccessDataFile(new File("/does/not/exist"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileNotNullWithConcurrentReads() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must not be null");
|
||||
new RandomAccessDataFile(null, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileExistsWithConcurrentReads() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must exist");
|
||||
new RandomAccessDataFile(new File("/does/not/exist"), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamRead() throws Exception {
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
assertThat(inputStream.read(), equalTo(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadNullBytes() throws Exception {
|
||||
thrown.expect(NullPointerException.class);
|
||||
thrown.expectMessage("Bytes must not be null");
|
||||
inputStream.read(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intputStreamReadNullBytesWithOffset() throws Exception {
|
||||
thrown.expect(NullPointerException.class);
|
||||
thrown.expectMessage("Bytes must not be null");
|
||||
inputStream.read(null, 0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadBytes() throws Exception {
|
||||
byte[] b = new byte[256];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, equalTo(BYTES));
|
||||
assertThat(amountRead, equalTo(256));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputSteamReadOffsetBytes() throws Exception {
|
||||
byte[] b = new byte[7];
|
||||
inputStream.skip(1);
|
||||
int amountRead = inputStream.read(b, 2, 3);
|
||||
assertThat(b, equalTo(new byte[] { 0, 0, 1, 2, 3, 0, 0 }));
|
||||
assertThat(amountRead, equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadMoreBytesThanAvailable() throws Exception {
|
||||
byte[] b = new byte[257];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, startsWith(BYTES));
|
||||
assertThat(amountRead, equalTo(256));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadPastEnd() throws Exception {
|
||||
inputStream.skip(255);
|
||||
assertThat(inputStream.read(), equalTo(0xFF));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadZeroLength() throws Exception {
|
||||
byte[] b = new byte[] { 0x0F };
|
||||
int amountRead = inputStream.read(b, 0, 0);
|
||||
assertThat(b, equalTo(new byte[] { 0x0F }));
|
||||
assertThat(amountRead, equalTo(0));
|
||||
assertThat(inputStream.read(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkip() throws Exception {
|
||||
long amountSkipped = inputStream.skip(4);
|
||||
assertThat(inputStream.read(), equalTo(4));
|
||||
assertThat(amountSkipped, equalTo(4L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipMoreThanAvailable() throws Exception {
|
||||
long amountSkipped = inputStream.skip(257);
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
assertThat(amountSkipped, equalTo(256L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipPastEnd() throws Exception {
|
||||
inputStream.skip(256);
|
||||
long amountSkipped = inputStream.skip(1);
|
||||
assertThat(amountSkipped, equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionNegativeOffset() throws Exception {
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(-1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionNegativeLength() throws Exception {
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(0, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionZeroLength() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(0, 0);
|
||||
assertThat(subsection.getInputStream().read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionTooBig() throws Exception {
|
||||
file.getSubsection(0, 256);
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(0, 257);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionTooBigWithOffset() throws Exception {
|
||||
file.getSubsection(1, 255);
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(1, 256);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 1);
|
||||
assertThat(subsection.getInputStream().read(), equalTo(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(2));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadBytesPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
byte[] b = new byte[3];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, equalTo(new byte[] { 1, 2, 0 }));
|
||||
assertThat(amountRead, equalTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
assertThat(inputStream.skip(3), equalTo(2L));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipNegative() throws Exception {
|
||||
assertThat(inputStream.skip(-1), equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile() throws Exception {
|
||||
assertThat(file.getFile(), equalTo(tempFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void concurrentReads() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(20);
|
||||
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
results.add(executorService.submit(new Callable<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
InputStream subsectionInputStream = file.getSubsection(0, 256)
|
||||
.getInputStream();
|
||||
byte[] b = new byte[256];
|
||||
subsectionInputStream.read(b);
|
||||
return Arrays.equals(b, BYTES);
|
||||
}
|
||||
}));
|
||||
}
|
||||
for (Future<Boolean> future : results) {
|
||||
assertThat(future.get(), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
file.getInputStream().read();
|
||||
file.close();
|
||||
Field filePoolField = RandomAccessDataFile.class.getDeclaredField("filePool");
|
||||
filePoolField.setAccessible(true);
|
||||
Object filePool = filePoolField.get(file);
|
||||
Field filesField = filePool.getClass().getDeclaredField("files");
|
||||
filesField.setAccessible(true);
|
||||
Queue<?> queue = (Queue<?>) filesField.get(filePool);
|
||||
assertThat(queue.size(), equalTo(0));
|
||||
}
|
||||
|
||||
private static Matcher<? super byte[]> startsWith(byte[] bytes) {
|
||||
return new ByteArrayStartsWith(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader.jar;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||
import org.springframework.boot.loader.jar.RandomAccessDataZipEntry;
|
||||
import org.springframework.boot.loader.jar.RandomAccessDataZipInputStream;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessDataZipInputStream}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataZipInputStreamTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File file;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.file = temporaryFolder.newFile();
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(file));
|
||||
try {
|
||||
writeDataEntry(zipOutputStream, "a", new byte[10]);
|
||||
writeDataEntry(zipOutputStream, "b", new byte[20]);
|
||||
}
|
||||
finally {
|
||||
zipOutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDataEntry(ZipOutputStream zipOutputStream, String name, byte[] data)
|
||||
throws IOException {
|
||||
ZipEntry entry = new ZipEntry(name);
|
||||
entry.setMethod(ZipEntry.STORED);
|
||||
entry.setSize(data.length);
|
||||
entry.setCompressedSize(data.length);
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(data);
|
||||
entry.setCrc(crc32.getValue());
|
||||
zipOutputStream.putNextEntry(entry);
|
||||
zipOutputStream.write(data);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entryData() throws Exception {
|
||||
RandomAccessDataZipInputStream z = new RandomAccessDataZipInputStream(
|
||||
new RandomAccessDataFile(file));
|
||||
try {
|
||||
RandomAccessDataZipEntry entry1 = z.getNextEntry();
|
||||
RandomAccessDataZipEntry entry2 = z.getNextEntry();
|
||||
assertThat(entry1.getName(), equalTo("a"));
|
||||
assertThat(entry1.getData().getSize(), equalTo(10L));
|
||||
assertThat(entry2.getName(), equalTo("b"));
|
||||
assertThat(entry2.getData().getSize(), equalTo(20L));
|
||||
assertThat(z.getNextEntry(), nullValue());
|
||||
}
|
||||
finally {
|
||||
z.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* 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.springframework.boot.loader.jar;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.boot.loader.TestJarCreator;
|
||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||
import org.springframework.boot.loader.jar.JarEntryFilter;
|
||||
import org.springframework.boot.loader.jar.RandomAccessJarFile;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessJarFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessJarFileTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootJarFile;
|
||||
|
||||
private RandomAccessJarFile jarFile;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.rootJarFile = this.temporaryFolder.newFile();
|
||||
TestJarCreator.createTestJar(this.rootJarFile);
|
||||
this.jarFile = new RandomAccessJarFile(this.rootJarFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromFile() throws Exception {
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(this.rootJarFile);
|
||||
assertThat(jarFile.getName(), notNullValue(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromRandomAccessDataFile() throws Exception {
|
||||
RandomAccessDataFile randomAccessDataFile = new RandomAccessDataFile(
|
||||
this.rootJarFile, 1);
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(randomAccessDataFile);
|
||||
assertThat(jarFile.getName(), notNullValue(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(this.jarFile.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Enumeration<JarEntry> entries = this.jarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/MANIFEST.MF"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("1.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("2.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("d/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("d/9.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("nested.jar"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getJarEntry() throws Exception {
|
||||
JarEntry entry = this.jarFile.getJarEntry("1.dat");
|
||||
assertThat(entry, notNullValue(ZipEntry.class));
|
||||
assertThat(entry.getName(), equalTo("1.dat"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInputStream() throws Exception {
|
||||
InputStream inputStream = this.jarFile.getInputStream(this.jarFile
|
||||
.getEntry("1.dat"));
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getName() throws Exception {
|
||||
assertThat(this.jarFile.getName(), equalTo(this.rootJarFile.getPath()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSize() throws Exception {
|
||||
assertThat(this.jarFile.size(), equalTo((int) this.rootJarFile.length()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
RandomAccessDataFile randomAccessDataFile = spy(new RandomAccessDataFile(
|
||||
this.rootJarFile, 1));
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(randomAccessDataFile);
|
||||
jarFile.close();
|
||||
verify(randomAccessDataFile).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = this.jarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/"));
|
||||
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
|
||||
assertThat(jarURLConnection.getJarFile(), sameInstance((JarFile) this.jarFile));
|
||||
assertThat(jarURLConnection.getJarEntry(), nullValue());
|
||||
assertThat(jarURLConnection.getContentLength(), greaterThan(1));
|
||||
assertThat(jarURLConnection.getContent(), sameInstance((Object) this.jarFile));
|
||||
assertThat(jarURLConnection.getContentType(), equalTo("x-java/jar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntryUrl() throws Exception {
|
||||
URL url = new URL(this.jarFile.getUrl(), "1.dat");
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/1.dat"));
|
||||
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
|
||||
assertThat(jarURLConnection.getJarFile(), sameInstance((JarFile) this.jarFile));
|
||||
assertThat(jarURLConnection.getJarEntry(),
|
||||
sameInstance(this.jarFile.getJarEntry("1.dat")));
|
||||
assertThat(jarURLConnection.getContentLength(), equalTo(1));
|
||||
assertThat(jarURLConnection.getContent(), instanceOf(InputStream.class));
|
||||
assertThat(jarURLConnection.getContentType(), equalTo("content/unknown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMissingEntryUrl() throws Exception {
|
||||
URL url = new URL(this.jarFile.getUrl(), "missing.dat");
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/missing.dat"));
|
||||
this.thrown.expect(FileNotFoundException.class);
|
||||
((JarURLConnection) url.openConnection()).getJarEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrlStream() throws Exception {
|
||||
URL url = this.jarFile.getUrl();
|
||||
url.openConnection();
|
||||
this.thrown.expect(IOException.class);
|
||||
url.openStream();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntryUrlStream() throws Exception {
|
||||
URL url = new URL(this.jarFile.getUrl(), "1.dat");
|
||||
url.openConnection();
|
||||
InputStream stream = url.openStream();
|
||||
assertThat(stream.read(), equalTo(1));
|
||||
assertThat(stream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedJarFile() throws Exception {
|
||||
RandomAccessJarFile nestedJarFile = this.jarFile.getNestedJarFile(this.jarFile
|
||||
.getEntry("nested.jar"));
|
||||
|
||||
Enumeration<JarEntry> entries = nestedJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/MANIFEST.MF"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("3.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("4.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = nestedJarFile.getInputStream(nestedJarFile
|
||||
.getEntry("3.dat"));
|
||||
assertThat(inputStream.read(), equalTo(3));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
|
||||
URL url = nestedJarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/nested.jar!/"));
|
||||
assertThat(((JarURLConnection) url.openConnection()).getJarFile(),
|
||||
sameInstance((JarFile) nestedJarFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedJarDirectory() throws Exception {
|
||||
RandomAccessJarFile nestedJarFile = this.jarFile.getNestedJarFile(this.jarFile
|
||||
.getEntry("d/"));
|
||||
|
||||
Enumeration<JarEntry> entries = nestedJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("9.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = nestedJarFile.getInputStream(nestedJarFile
|
||||
.getEntry("9.dat"));
|
||||
assertThat(inputStream.read(), equalTo(9));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
|
||||
URL url = nestedJarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath()
|
||||
+ "!/d!/"));
|
||||
assertThat(((JarURLConnection) url.openConnection()).getJarFile(),
|
||||
sameInstance((JarFile) nestedJarFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDirectoryInputStream() throws Exception {
|
||||
InputStream inputStream = this.jarFile
|
||||
.getInputStream(this.jarFile.getEntry("d/"));
|
||||
assertThat(inputStream, notNullValue());
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDirectoryInputStreamWithoutSlash() throws Exception {
|
||||
InputStream inputStream = this.jarFile.getInputStream(this.jarFile.getEntry("d"));
|
||||
assertThat(inputStream, notNullValue());
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredJarFile() throws Exception {
|
||||
RandomAccessJarFile filteredJarFile = this.jarFile
|
||||
.getFilteredJarFile(new JarEntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, JarEntry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return "x.dat";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Enumeration<JarEntry> entries = filteredJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("x.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = filteredJarFile.getInputStream(filteredJarFile
|
||||
.getEntry("x.dat"));
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensibleToString() throws Exception {
|
||||
assertThat(this.jarFile.toString(), equalTo(this.rootJarFile.getPath()));
|
||||
assertThat(this.jarFile.getNestedJarFile(this.jarFile.getEntry("nested.jar"))
|
||||
.toString(), equalTo(this.rootJarFile.getPath() + "!/nested.jar"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user