package net.bytebuddy.dynamic.loading;
import net.bytebuddy.test.utility.IntegrationRule;
import net.bytebuddy.test.utility.JavaVersionRule;
import net.bytebuddy.test.utility.MockitoRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestRule;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Iterator;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
public class PackageTypeStrategyManifestReadingTest {
private static final String FOO = "foo", BAR = "bar", QUX = "qux", BAZ = "baz";
@Rule
public MethodRule integrationRule = new IntegrationRule();
@Rule
public MethodRule javaVersionRule = new JavaVersionRule();
@Rule
public TestRule mockitoRule = new MockitoRule(this);
@Mock
private PackageDefinitionStrategy.ManifestReading.SealBaseLocator sealBaseLocator;
@Mock
private ClassLoader classLoader;
private URL url;
@Before
public void setUp() throws Exception {
url = new URL("file:/foo");
}
@Test
public void testNoManifest() throws Exception {
PackageDefinitionStrategy packageDefinitionStrategy = new PackageDefinitionStrategy.ManifestReading(sealBaseLocator);
PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, FOO, BAR);
assertThat(definition.isDefined(), is(true));
assertThat(definition.getImplementationTitle(), nullValue(String.class));
assertThat(definition.getImplementationVersion(), nullValue(String.class));
assertThat(definition.getImplementationVendor(), nullValue(String.class));
assertThat(definition.getSpecificationTitle(), nullValue(String.class));
assertThat(definition.getSpecificationVersion(), nullValue(String.class));
assertThat(definition.getSpecificationVendor(), nullValue(String.class));
assertThat(definition.getSealBase(), nullValue(URL.class));
assertThat(definition.isCompatibleTo(getClass().getPackage()), is(true));
verifyZeroInteractions(sealBaseLocator);
}
@Test
public void testManifestMainAttributesNotSealed() throws Exception {
final Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE, FOO);
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_VERSION, BAR);
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_VENDOR, QUX);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_TITLE, BAZ);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VERSION, FOO + BAR);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VENDOR, QUX + BAZ);
manifest.getMainAttributes().put(Attributes.Name.SEALED, Boolean.FALSE.toString());
when(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF")).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
manifest.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
}
});
PackageDefinitionStrategy packageDefinitionStrategy = new PackageDefinitionStrategy.ManifestReading(sealBaseLocator);
PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, FOO + "." + BAR, FOO + "." + BAR + "." + QUX);
assertThat(definition.isDefined(), is(true));
assertThat(definition.getSpecificationTitle(), is(FOO));
assertThat(definition.getSpecificationVersion(), is(BAR));
assertThat(definition.getSpecificationVendor(), is(QUX));
assertThat(definition.getImplementationTitle(), is(BAZ));
assertThat(definition.getImplementationVersion(), is(FOO + BAR));
assertThat(definition.getImplementationVendor(), is(QUX + BAZ));
assertThat(definition.getSealBase(), nullValue(URL.class));
assertThat(definition.isCompatibleTo(getClass().getPackage()), is(true));
verifyZeroInteractions(sealBaseLocator);
}
@Test
public void testManifestPackageAttributesNotSealed() throws Exception {
final Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_VERSION, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.SPECIFICATION_VENDOR, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_TITLE, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VERSION, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.IMPLEMENTATION_VENDOR, FOO + QUX);
manifest.getMainAttributes().put(Attributes.Name.SEALED, FOO + QUX);
manifest.getEntries().put(FOO + "/" + BAR + "/", new Attributes());
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.SPECIFICATION_TITLE, FOO);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.SPECIFICATION_VERSION, BAR);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.SPECIFICATION_VENDOR, QUX);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.IMPLEMENTATION_TITLE, BAZ);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.IMPLEMENTATION_VERSION, FOO + BAR);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.IMPLEMENTATION_VENDOR, QUX + BAZ);
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.SEALED, Boolean.FALSE.toString());
when(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF")).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
manifest.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
}
});
PackageDefinitionStrategy packageDefinitionStrategy = new PackageDefinitionStrategy.ManifestReading(sealBaseLocator);
PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, FOO + "." + BAR, FOO + "." + BAR + "." + QUX);
assertThat(definition.isDefined(), is(true));
assertThat(definition.getSpecificationTitle(), is(FOO));
assertThat(definition.getSpecificationVersion(), is(BAR));
assertThat(definition.getSpecificationVendor(), is(QUX));
assertThat(definition.getImplementationTitle(), is(BAZ));
assertThat(definition.getImplementationVersion(), is(FOO + BAR));
assertThat(definition.getImplementationVendor(), is(QUX + BAZ));
assertThat(definition.getSealBase(), nullValue(URL.class));
assertThat(definition.isCompatibleTo(getClass().getPackage()), is(true));
verifyZeroInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
public void testManifestMainAttributesSealed() throws Exception {
final Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().put(Attributes.Name.SEALED, Boolean.TRUE.toString());
when(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF")).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
manifest.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
}
});
when(sealBaseLocator.findSealBase(classLoader, FOO + "." + BAR + "." + QUX)).thenReturn(url);
PackageDefinitionStrategy packageDefinitionStrategy = new PackageDefinitionStrategy.ManifestReading(sealBaseLocator);
PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, FOO + "." + BAR, FOO + "." + BAR + "." + QUX);
assertThat(definition.isDefined(), is(true));
assertThat(definition.getSealBase(), is(url));
verify(sealBaseLocator).findSealBase(classLoader, FOO + "." + BAR + "." + QUX);
verifyNoMoreInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
public void testManifestPackageAttributesSealed() throws Exception {
final Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getEntries().put(FOO + "/" + BAR + "/", new Attributes());
manifest.getAttributes(FOO + "/" + BAR + "/").put(Attributes.Name.SEALED, Boolean.TRUE.toString());
when(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF")).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
manifest.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
}
});
when(sealBaseLocator.findSealBase(classLoader, FOO + "." + BAR + "." + QUX)).thenReturn(url);
PackageDefinitionStrategy packageDefinitionStrategy = new PackageDefinitionStrategy.ManifestReading(sealBaseLocator);
PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, FOO + "." + BAR, FOO + "." + BAR + "." + QUX);
assertThat(definition.isDefined(), is(true));
assertThat(definition.getSealBase(), is(url));
verify(sealBaseLocator).findSealBase(classLoader, FOO + "." + BAR + "." + QUX);
verifyNoMoreInteractions(sealBaseLocator);
}
@Test
public void testSealBaseLocatorNonSealing() throws Exception {
assertThat(PackageDefinitionStrategy.ManifestReading.SealBaseLocator.NonSealing.INSTANCE.findSealBase(classLoader, FOO), nullValue(URL.class));
}
@Test
@IntegrationRule.Enforce
public void testSealBaseLocatorForFixedValue() throws Exception {
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForFixedValue(url).findSealBase(classLoader, FOO), is(url));
}
@Test
@IntegrationRule.Enforce
public void testSealBaseLocatorForTypeResourceUrlUnknownUrl() throws Exception {
when(sealBaseLocator.findSealBase(classLoader, FOO + "." + BAR)).thenReturn(url);
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl(sealBaseLocator)
.findSealBase(classLoader, FOO + "." + BAR), is(url));
verify(sealBaseLocator).findSealBase(classLoader, FOO + "." + BAR);
verifyNoMoreInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
public void testSealBaseLocatorForTypeResourceUrlFileUrl() throws Exception {
URL url = new URL("file:/foo");
when(classLoader.getResource(FOO + "/" + BAR + ".class")).thenReturn(url);
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl(sealBaseLocator)
.findSealBase(classLoader, FOO + "." + BAR), is(url));
verifyZeroInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
public void testSealBaseLocatorForTypeResourceUrlJarUrl() throws Exception {
URL url = new URL("jar:file:/foo.jar!/bar");
when(classLoader.getResource(FOO + "/" + BAR + ".class")).thenReturn(url);
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl(sealBaseLocator)
.findSealBase(classLoader, FOO + "." + BAR), is(new URL("file:/foo.jar")));
verifyZeroInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
@JavaVersionRule.Enforce(9)
public void testSealBaseLocatorForTypeResourceUrlJavaRuntimeImageUrl() throws Exception {
URL url = new URL("jrt:/foo/bar");
when(classLoader.getResource(FOO + "/" + BAR + ".class")).thenReturn(url);
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl(sealBaseLocator)
.findSealBase(classLoader, FOO + "." + BAR), is(new URL("jrt:/foo")));
verifyZeroInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
@JavaVersionRule.Enforce(9)
public void testSealBaseLocatorForTypeResourceUrlJavaRuntimeImageUrlRawModule() throws Exception {
URL url = new URL("jrt:/foo");
when(classLoader.getResource(FOO + "/" + BAR + ".class")).thenReturn(url);
assertThat(new PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl(sealBaseLocator)
.findSealBase(classLoader, FOO + "." + BAR), is(new URL("jrt:/foo")));
verifyZeroInteractions(sealBaseLocator);
}
@Test
@IntegrationRule.Enforce
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(PackageDefinitionStrategy.ManifestReading.class).apply();
ObjectPropertyAssertion.of(PackageDefinitionStrategy.ManifestReading.SealBaseLocator.NonSealing.class).apply();
final Iterator<URL> urls = Arrays.asList(new URL("file://foo"), new URL("file://bar")).iterator();
ObjectPropertyAssertion.of(PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForFixedValue.class)
.create(new ObjectPropertyAssertion.Creator<URL>() {
@Override
public URL create() {
return urls.next();
}
}).apply();
ObjectPropertyAssertion.of(PackageDefinitionStrategy.ManifestReading.SealBaseLocator.ForTypeResourceUrl.class).apply();
}
}