diff --git a/spring-boot-parent/pom.xml b/spring-boot-parent/pom.xml index d1ecb8f34d6..3bba7234848 100644 --- a/spring-boot-parent/pom.xml +++ b/spring-boot-parent/pom.xml @@ -98,6 +98,11 @@ maven-settings-builder ${maven.version} + + org.apache.maven.shared + maven-common-artifact-filters + 1.4 + org.apache.maven.plugins maven-shade-plugin diff --git a/spring-boot-tools/spring-boot-maven-plugin/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/pom.xml index 93b94ea879a..47cb11090e9 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/pom.xml +++ b/spring-boot-tools/spring-boot-maven-plugin/pom.xml @@ -126,6 +126,10 @@ org.apache.maven maven-settings + + org.apache.maven.shared + maven-common-artifact-filters + org.codehaus.plexus plexus-archiver diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/pom.xml new file mode 100644 index 00000000000..02747a078df --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + org.springframework.boot.maven.it + jar-exclude-artifact + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + repackage + + + servlet-api + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + Foo + + + + + + + + + org.springframework + spring-context + 3.2.3.RELEASE + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + javax.servlet + servlet-api + 2.5 + provided + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..0b3b431677d --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,8 @@ +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/verify.groovy new file mode 100644 index 00000000000..be667d68820 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-artifact/verify.groovy @@ -0,0 +1,11 @@ +import java.io.*; +import org.springframework.boot.maven.*; + +File f = new File( basedir, "target/jar-exclude-artifact-0.0.1.BUILD-SNAPSHOT.jar"); +new Verify.JarArchiveVerification(f, Verify.SAMPLE_APP) { + @Override + protected void verifyZipEntries(Verify.ArchiveVerifier verifier) throws Exception { + super.verifyZipEntries(verifier) + verifier.assertHasNoEntryNameStartingWith("lib/servlet-api-2.5.jar") + } +}.verify(); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/pom.xml new file mode 100644 index 00000000000..00bdeb2f851 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/pom.xml @@ -0,0 +1,82 @@ + + + + + 4.0.0 + org.springframework.boot.maven.it + jar-exclude-entry + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + repackage + + + + + javax.servlet + servlet-api + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + Foo + + + + + + + + + org.springframework + spring-context + 3.2.3.RELEASE + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + javax.servlet + servlet-api + 2.5 + provided + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..0b3b431677d --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,8 @@ +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/verify.groovy new file mode 100644 index 00000000000..4f27fc368d9 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-entry/verify.groovy @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 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. + */ + +import java.io.*; +import org.springframework.boot.maven.*; + +File f = new File( basedir, "target/jar-exclude-entry-0.0.1.BUILD-SNAPSHOT.jar"); +new Verify.JarArchiveVerification(f, Verify.SAMPLE_APP) { + @Override + protected void verifyZipEntries(Verify.ArchiveVerifier verifier) throws Exception { + super.verifyZipEntries(verifier) + verifier.assertHasNoEntryNameStartingWith("lib/servlet-api-2.5.jar") + } +}.verify(); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/pom.xml new file mode 100644 index 00000000000..c8bae6c3a78 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/pom.xml @@ -0,0 +1,76 @@ + + + + + 4.0.0 + org.springframework.boot.maven.it + jar-exclude-group + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + repackage + + + log4j + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + Foo + + + + + + + + + org.springframework + spring-context + 3.2.3.RELEASE + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + log4j + log4j + 1.2.17 + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..0b3b431677d --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,8 @@ +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/verify.groovy new file mode 100644 index 00000000000..f03bbb3a839 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-exclude-group/verify.groovy @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 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. + */ + +import java.io.*; +import org.springframework.boot.maven.*; + +File f = new File( basedir, "target/jar-exclude-group-0.0.1.BUILD-SNAPSHOT.jar"); +new Verify.JarArchiveVerification(f, Verify.SAMPLE_APP) { + @Override + protected void verifyZipEntries(Verify.ArchiveVerifier verifier) throws Exception { + super.verifyZipEntries(verifier) + verifier.assertHasNoEntryNameStartingWith("lib/log4j-1.2.17.jar") + } +}.verify(); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/pom.xml new file mode 100644 index 00000000000..1426be6b19d --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + org.springframework.boot.maven.it + jar-test-scope + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + repackage + + + servlet-api + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + Foo + + + + + + + + + org.springframework + spring-context + 3.2.3.RELEASE + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + log4j + log4j + 1.2.17 + test + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..0b3b431677d --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,8 @@ +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/verify.groovy new file mode 100644 index 00000000000..b76415b150b --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/jar-test-scope/verify.groovy @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 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. + */ + +import java.io.*; +import org.springframework.boot.maven.*; + +File f = new File( basedir, "target/jar-test-scope-0.0.1.BUILD-SNAPSHOT.jar"); +new Verify.JarArchiveVerification(f, Verify.SAMPLE_APP) { + @Override + protected void verifyZipEntries(Verify.ArchiveVerifier verifier) throws Exception { + super.verifyZipEntries(verifier) + verifier.assertHasNoEntryNameStartingWith("lib/log4j-1.2.17.jar") + } +}.verify(); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/pom.xml new file mode 100644 index 00000000000..f48531ad0cc --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + org.springframework.boot.maven.it + run-exclude + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + package + + run + + + + + log4j + log4j + + + javax.servlet + + + + + + + + + log4j + log4j + 1.2.17 + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + javax.servlet + servlet-api + 2.5 + provided + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..6f0d38785a0 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,27 @@ +package org.test; + +public class SampleApplication { + + public static void main(String[] args) { + if (isClassPresent("org.apache.log4j.Logger")) { + throw new IllegalStateException("Log4j was present and should not"); + } + if (isClassPresent("javax.servlet.Servlet")) { + throw new IllegalStateException("servlet-api was present and should not"); + } + System.out.println("I haz been run"); + } + + private static boolean isClassPresent(String className) { + + try { + ClassLoader classLoader = SampleApplication.class.getClassLoader(); + classLoader.loadClass(className); + return true; + } + catch (ClassNotFoundException e) { + return false; + } + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/verify.groovy new file mode 100644 index 00000000000..841c4a97de5 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-exclude/verify.groovy @@ -0,0 +1,3 @@ +def file = new File(basedir, "build.log") +return file.text.contains("I haz been run") + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/run/pom.xml index af6bbbc2c78..092e362c671 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/it/run/pom.xml +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run/pom.xml @@ -16,7 +16,6 @@ @project.version@ - package run diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java new file mode 100644 index 00000000000..954735dded3 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractDependencyFilterMojo.java @@ -0,0 +1,111 @@ +/* + * Copyright 2012-2014 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.maven; + +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException; +import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter; +import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; +import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter; + +/** + * A base mojo filtering the dependencies of the project. + * + * @author Stephane Nicoll + * @since 1.1 + */ +public abstract class AbstractDependencyFilterMojo extends AbstractMojo { + + /** + * Collection of artifact definitions to exclude. The {@link Exclude} + * element defines a {@code groupId} and {@code artifactId} mandatory + * properties and an optional {@code classifier} property. + * @since 1.1 + */ + @Parameter + private List excludes; + + /** + * Comma separated list of groupId names to exclude. + * @since 1.1 + */ + @Parameter(property = "excludeGroupIds", defaultValue = "") + protected String excludeGroupIds; + + /** + * Comma separated list of artifact names to exclude. + * @since 1.1 + */ + @Parameter(property = "excludeArtifactIds", defaultValue = "") + protected String excludeArtifactIds; + + + protected void setExcludes(List excludes) { + this.excludes = excludes; + } + + protected void setExcludeGroupIds(String excludeGroupIds) { + this.excludeGroupIds = excludeGroupIds; + } + + protected void setExcludeArtifactIds(String excludeArtifactIds) { + this.excludeArtifactIds = excludeArtifactIds; + } + + @SuppressWarnings("unchecked") + protected Set filterDependencies(Set dependencies, FilterArtifacts filters) + throws MojoExecutionException { + try { + return filters.filter(dependencies); + } + catch (ArtifactFilterException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + protected void initializeFilterArtifacts(FilterArtifacts filters) { + filters.addFilter(new ArtifactIdFilter("", cleanConfigItem(this.excludeArtifactIds))); + filters.addFilter(new GroupIdFilter("", cleanConfigItem(this.excludeGroupIds))); + if (this.excludes != null) { + filters.addFilter(new ExcludeFilter(this.excludes)); + } + } + + + static String cleanConfigItem(String content) { + if (content == null || content.trim().isEmpty()) { + return ""; + } + StringBuilder sb = new StringBuilder(); + StringTokenizer st = new StringTokenizer(content, ","); + while (st.hasMoreElements()) { + String t = st.nextToken(); + sb.append(t.trim()); + if (st.hasMoreElements()) { + sb.append(","); + } + } + return sb.toString(); + } +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java new file mode 100644 index 00000000000..26642e41686 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/Exclude.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2014 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.maven; + +import org.apache.maven.plugins.annotations.Parameter; + +/** + * A model for a dependency to exclude. + * + * @author Stephane Nicoll + * @since 1.1 + */ +public class Exclude { + + /** + * The groupId of the artifact to exclude. + */ + @Parameter(required = true) + private String groupId; + + /** + * The artifactId of the artifact to exclude. + */ + @Parameter(required = true) + private String artifactId; + + /** + * The classifier of the artifact to exclude + */ + @Parameter + private String classifier; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getClassifier() { + return classifier; + } + + public void setClassifier(String classifier) { + this.classifier = classifier; + } +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java new file mode 100644 index 00000000000..523995346b0 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/ExcludeFilter.java @@ -0,0 +1,88 @@ +/* + * Copyright 2012-2014 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.maven; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter; +import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException; + +/** + * An {@link org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter + * ArtifactsFilter} that filters out any artifact matching a configurable list + * of {@link Exclude} instances. + * + * @author Stephane Nicoll + * @since 1.1 + */ +public class ExcludeFilter extends AbstractArtifactsFilter{ + + private final List excludes; + + /** + * Create a new instance with the list of {@link Exclude} + * instance(s) to use. + */ + public ExcludeFilter(List excludes) { + this.excludes = excludes; + } + + @Override + public Set filter(Set artifacts) throws ArtifactFilterException { + Set result = new HashSet(); + for (Object a : artifacts) { + Artifact artifact = (Artifact) a; + if (!matchExclude(artifact)) { + result.add(artifact); + } + } + return result; + } + + /** + * Check if the specified {@link Artifact} matches one of the + * known excludes. Returns {@code true} if it should be excluded + */ + private boolean matchExclude(Artifact artifact) { + for (Exclude exclude : excludes) { + if (match(artifact, exclude)) { + return true; + } + } + return false; + } + + /** + * Check if the specified {@link Artifact} matches the specified + * {@link Exclude}. Returns {@code true} if it should be excluded + */ + private boolean match(Artifact artifact, Exclude exclude) { + if (!exclude.getGroupId().equals(artifact.getGroupId())) { + return false; + } + if (!exclude.getArtifactId().equals(artifact.getArtifactId())) { + return false; + } + return exclude.getClassifier() == null || + artifact.getClassifier() != null && exclude.getClassifier().equals(artifact.getClassifier()); + + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java index c008a28b30a..fee277d1a26 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java @@ -18,9 +18,11 @@ package org.springframework.boot.maven; import java.io.File; import java.io.IOException; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.jar.JarFile; +import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -31,6 +33,8 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; +import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; + import org.springframework.boot.loader.tools.Layout; import org.springframework.boot.loader.tools.Layouts; import org.springframework.boot.loader.tools.Libraries; @@ -46,7 +50,7 @@ import org.springframework.boot.loader.tools.Repackager; * @author Stephane Nicoll */ @Mojo(name = "repackage", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) -public class RepackageMojo extends AbstractMojo { +public class RepackageMojo extends AbstractDependencyFilterMojo { private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10); @@ -134,7 +138,12 @@ public class RepackageMojo extends AbstractMojo { getLog().info("Layout: " + this.layout); repackager.setLayout(this.layout.layout()); } - Libraries libraries = new ArtifactsLibraries(this.project.getArtifacts()); + + FilterArtifacts filters = new FilterArtifacts(); + initializeFilterArtifacts(filters); + Set artifacts = filterDependencies(this.project.getArtifacts(), filters); + + Libraries libraries = new ArtifactsLibraries(artifacts); try { repackager.repackage(target, libraries); } diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java index 434a44a8820..6ea9857454a 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java @@ -24,10 +24,10 @@ import java.security.CodeSource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Resource; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Execute; @@ -36,6 +36,9 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; +import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactFeatureFilter; +import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; + import org.springframework.boot.loader.tools.FileUtils; import org.springframework.boot.loader.tools.JavaExecutable; import org.springframework.boot.loader.tools.MainClassFinder; @@ -43,13 +46,13 @@ import org.springframework.boot.loader.tools.RunProcess; /** * Run an executable archive application. - * + * * @author Phillip Webb * @author Stephane Nicoll */ @Mojo(name = "run", requiresProject = true, defaultPhase = LifecyclePhase.VALIDATE, requiresDependencyResolution = ResolutionScope.TEST) @Execute(phase = LifecyclePhase.TEST_COMPILE) -public class RunMojo extends AbstractMojo { +public class RunMojo extends AbstractDependencyFilterMojo { private static final String SPRING_LOADED_AGENT_CLASSNAME = "org.springsource.loaded.agent.SpringLoadedAgent"; @@ -253,14 +256,27 @@ public class RunMojo extends AbstractMojo { urls.add(this.classesDirectory.toURI().toURL()); } - private void addDependencies(List urls) throws MalformedURLException { - for (Artifact artifact : this.project.getArtifacts()) { + private void addDependencies(List urls) throws MalformedURLException, MojoExecutionException { + FilterArtifacts filters = new FilterArtifacts(); + filters.addFilter(new TestArtifactFilter()); + initializeFilterArtifacts(filters); + + Set artifacts = filterDependencies(this.project.getArtifacts(), filters); + for (Artifact artifact : artifacts) { if (artifact.getFile() != null) { - if (!Artifact.SCOPE_TEST.equals(artifact.getScope())) { - urls.add(artifact.getFile().toURI().toURL()); - } + urls.add(artifact.getFile().toURI().toURL()); } } } + private static class TestArtifactFilter extends AbstractArtifactFeatureFilter { + public TestArtifactFilter() { + super("", Artifact.SCOPE_TEST); + } + + protected String getArtifactFeature(Artifact artifact) { + return artifact.getScope(); + } + } + } diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/exclude-dependency.apt.vm b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/exclude-dependency.apt.vm new file mode 100644 index 00000000000..77985559ed3 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/exclude-dependency.apt.vm @@ -0,0 +1,117 @@ + ----- + Exclude a dependency + ----- + Stephane Nicoll + ----- + 2014-05-06 + ----- + + By default, both the <<>> and the <<>> goals will include any <<>> + dependencies that are defined in the project. A boot-based project should consider + <<>> dependencies as <> dependencies that are required to run + the application. + + Some of these dependencies may not be required at all and should be excluded from the + executable jar. For consistency, they should not be present either when running the + application. + + There are tree ways one can exclude a dependency from being packaged/used at runtime + + * Exclude a specific artifact identified by <<>> and <<>> + (optionnaly with a <<>> if needed) + + * Exclude any artifact matching a given <<>> + + * Exclude any artifact belonging to a given <<>> + + [] + + The following excludes <<>> (and only that artifact) + +--- + + ... + + ... + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + + com.foo + bar + + + + ... + + ... + + ... + + ... + +--- + + This example excludes every artifacts having the <<>> or <<>> + artifact identifiers + +--- + + ... + + ... + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + my-lib,another-lib + + + ... + + ... + + ... + + ... + +--- + + Finally this example excludes any artifact belonging to the <<>> group + + +--- + + ... + + ... + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + com.foo + + + ... + + ... + + ... + + ... + +--- + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/repackage-classifier.apt b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/repackage-classifier.apt.vm similarity index 100% rename from spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/repackage-classifier.apt rename to spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/repackage-classifier.apt.vm diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt index c820748c17c..b7f2e3f4128 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt +++ b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/index.apt @@ -38,6 +38,8 @@ Spring Boot Maven Plugin * {{{./examples/repackage-classifier.html}Custom repackage classifier}} + * {{{./examples/exclude-dependency.html}Exclude a dependency}} + [] diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm index 7b3e5c0d481..9afbd2544e2 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm +++ b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/usage.apt.vm @@ -4,7 +4,7 @@ ----- Stephane Nicoll ----- - 2014-05-02 + 2014-05-06 ----- Usage @@ -40,9 +40,13 @@ Usage --- - The example above repackages a jar or war that is built during the package phase of the Maven lifecycle. The - original (i.e. non exectuable) artifact is renamed to <<<.original>>> by default but it is also possible to - keep the original artifact using a custom classifier. + The example above repackages a jar or war that is built during the package phase of the Maven lifecycle, + including any <<>> dependencies that are defined in the project. If some of these dependencies + need to be excluded, you can use one of the exclude options, + see {{{./examples/exclude-dependency.html}Exclude a dependency}} for more details. + + The original (i.e. non exectuable) artifact is renamed to <<<.original>>> by default but it is also + possible to keep the original artifact using a custom classifier. The plugin rewrites your manifest, and in particular it manages the <> and <> entries, so if the defaults don't work you have to configure those there (not in the jar plugin). The @@ -82,6 +86,8 @@ Usage * {{{./examples/repackage-classifier.html}Custom repackage classifier}} + * {{{./examples/exclude-dependency.html}Exclude a dependency}} + [] * Running the application @@ -120,4 +126,9 @@ mvn spring-boot:run ... ---- \ No newline at end of file +--- + + In order to be consistent with the <<>> goal, the <<>> goal builds the classpath + in such a way that any dependency that is excluded in the plugin's configuration gets excluded + from the classpath as well. See {{{./examples/exclude-dependency.html}Exclude a dependency}} for + more details. \ No newline at end of file diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml b/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml index 73c82ec3067..93cddec5b74 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml +++ b/spring-boot-tools/spring-boot-maven-plugin/src/site/site.xml @@ -8,6 +8,7 @@ + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java new file mode 100644 index 00000000000..bbbad742d8a --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/DependencyFilterMojoTests.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2014 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.maven; + +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; +import org.junit.Test; + +/** + * + * @author Stephane Nicoll + */ +public class DependencyFilterMojoTests { + + @Test + public void filterDependencies() throws MojoExecutionException { + TestableDependencyFilterMojo mojo = new TestableDependencyFilterMojo( + Collections.emptyList(), "com.foo", "exclude-id"); + + Artifact artifact = createArtifact("com.bar", "one"); + Set artifacts = mojo.filterDependencies(createArtifact("com.foo", "one"), + createArtifact("com.foo", "two"), + createArtifact("com.bar", "exclude-id"), + artifact); + assertEquals("wrong filtering of artifacts", 1, artifacts.size()); + assertSame("Wrong filtered artifact", artifact, artifacts.iterator().next()); + } + + + + private Artifact createArtifact(String groupId, String artifactId) { + Artifact a = mock(Artifact.class); + given(a.getGroupId()).willReturn(groupId); + given(a.getArtifactId()).willReturn(artifactId); + return a; + } + + + private static class TestableDependencyFilterMojo extends AbstractDependencyFilterMojo { + + private TestableDependencyFilterMojo(List excludes, String excludeGroupIds, String excludeArtifactIds) { + setExcludes(excludes); + setExcludeGroupIds(excludeGroupIds); + setExcludeArtifactIds(excludeArtifactIds); + } + + public Set filterDependencies(Artifact... artifacts) throws MojoExecutionException { + Set input = new HashSet(Arrays.asList(artifacts)); + FilterArtifacts filters = new FilterArtifacts(); + initializeFilterArtifacts(filters); + return filterDependencies(input, filters); + } + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + } + } +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ExcludeFilterTests.java b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ExcludeFilterTests.java new file mode 100644 index 00000000000..ed1da0f6e03 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/ExcludeFilterTests.java @@ -0,0 +1,131 @@ +/* + * Copyright 2012-2014 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.maven; + +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; +import static org.mockito.Mockito.mock; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException; +import org.junit.Test; + +/** + * + * @author Stephane Nicoll + */ +public class ExcludeFilterTests { + + + @Test + public void excludeSimple() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar"))); + Set result = filter.filter(Collections.singleton(createArtifact("com.foo", "bar"))); + assertEquals("Should have been filtered", 0, result.size()); + } + + @Test + public void excludeGroupIdNoMatch() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar"))); + Artifact artifact = createArtifact("com.baz", "bar"); + Set result = filter.filter(Collections.singleton(artifact)); + assertEquals("Should not have been filtered", 1, result.size()); + assertSame(artifact, result.iterator().next()); + } + + @Test + public void excludeArtifactIdNoMatch() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar"))); + Artifact artifact = createArtifact("com.foo", "biz"); + Set result = filter.filter(Collections.singleton(artifact)); + assertEquals("Should not have been filtered", 1, result.size()); + assertSame(artifact, result.iterator().next()); + } + + @Test + public void excludeClassifier() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar", "jdk5"))); + Set result = filter.filter(Collections.singleton(createArtifact("com.foo", "bar", "jdk5"))); + assertEquals("Should have been filtered", 0, result.size()); + } + + @Test + public void excludeClassifierNoTargetClassifier() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar", "jdk5"))); + Artifact artifact = createArtifact("com.foo", "bar"); + Set result = filter.filter(Collections.singleton(artifact)); + assertEquals("Should not have been filtered", 1, result.size()); + assertSame(artifact, result.iterator().next()); + } + + @Test + public void excludeClassifierNoMatch() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList(createExclude("com.foo", "bar", "jdk5"))); + Artifact artifact = createArtifact("com.foo", "bar", "jdk6"); + Set result = filter.filter(Collections.singleton(artifact)); + assertEquals("Should not have been filtered", 1, result.size()); + assertSame(artifact, result.iterator().next()); + } + + @Test + public void excludeMulti() throws ArtifactFilterException { + ExcludeFilter filter = new ExcludeFilter(Arrays.asList( + createExclude("com.foo", "bar"), + createExclude("com.foo", "bar2"), + createExclude("org.acme", "app"))); + Set artifacts = new HashSet(); + artifacts.add(createArtifact("com.foo", "bar")); + artifacts.add(createArtifact("com.foo", "bar")); + Artifact anotherAcme = createArtifact("org.acme", "another-app"); + artifacts.add(anotherAcme); + Set result = filter.filter(artifacts); + assertEquals("Two dependencies should have been filtered", 1, result.size()); + assertSame(anotherAcme, result.iterator().next()); + } + + + private Exclude createExclude(String groupId, String artifactId, String classifier) { + Exclude e = new Exclude(); + e.setGroupId(groupId); + e.setArtifactId(artifactId); + if (classifier != null) { + e.setClassifier(classifier); + } + return e; + } + + private Exclude createExclude(String groupId, String artifactId) { + return createExclude(groupId, artifactId, null); + } + + private Artifact createArtifact(String groupId, String artifactId, String classifier) { + Artifact a = mock(Artifact.class); + given(a.getGroupId()).willReturn(groupId); + given(a.getArtifactId()).willReturn(artifactId); + given(a.getClassifier()).willReturn(classifier); + return a; + } + + private Artifact createArtifact(String groupId, String artifactId) { + return createArtifact(groupId, artifactId, null); + } +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RepackageMojoTests.java b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RepackageMojoTests.java new file mode 100644 index 00000000000..1ce9810653f --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/RepackageMojoTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2014 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.maven; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * + * @author Stephane Nicoll + */ +public class RepackageMojoTests { + + + @Test + public void cleanConfigItemWithSpaces() { + assertEquals("foo,bar,biz", RepackageMojo.cleanConfigItem("foo, bar , biz")); + } + + @Test + public void cleanNullConfigItemWith() { + assertEquals("", RepackageMojo.cleanConfigItem(null)); + } + + @Test + public void cleanEmptyConfigItemWith() { + assertEquals("", RepackageMojo.cleanConfigItem("")); + } +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/Verify.java b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/Verify.java index 84a3ff75e29..ebd4f7461b5 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/Verify.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/test/java/org/springframework/boot/maven/Verify.java @@ -17,6 +17,8 @@ package org.springframework.boot.maven; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -34,8 +36,10 @@ import static org.junit.Assert.assertTrue; */ public class Verify { + public static final String SAMPLE_APP = "org.test.SampleApplication"; + public static void verifyJar(File file) throws Exception { - new JarArchiveVerification(file, "org.test.SampleApplication").verify(); + new JarArchiveVerification(file, SAMPLE_APP).verify(); } public static void verifyJar(File file, String main) throws Exception { @@ -50,6 +54,57 @@ public class Verify { new ZipArchiveVerification(file).verify(); } + public static class ArchiveVerifier { + + private final ZipFile zipFile; + private final Map content; + + public ArchiveVerifier(ZipFile zipFile) { + this.zipFile = zipFile; + Enumeration entries = zipFile.entries(); + this.content = new HashMap(); + while (entries.hasMoreElements()) { + ZipEntry zipEntry = entries.nextElement(); + this.content.put(zipEntry.getName(), zipEntry); + } + } + + public void assertHasEntryNameStartingWith(String entry) { + for (String name : this.content.keySet()) { + if (name.startsWith(entry)) { + return; + } + } + throw new IllegalStateException("Expected entry starting with " + entry); + } + + public void assertHasNoEntryNameStartingWith(String entry) { + for (String name : this.content.keySet()) { + if (name.startsWith(entry)) { + throw new IllegalStateException("Entry starting with " + + entry + " should not have been found"); + } + } + } + + public boolean hasEntry(String entry) { + return this.content.containsKey(entry); + } + + public ZipEntry getEntry(String entry) { + return this.content.get(entry); + } + + public InputStream getEntryContent(String entry) throws IOException { + ZipEntry zipEntry = getEntry(entry); + if (zipEntry == null) { + throw new IllegalArgumentException("No entry with name ["+entry+"]"); + } + return this.zipFile.getInputStream(zipEntry); + } + + } + private static abstract class AbstractArchiveVerification { private final File file; @@ -63,40 +118,30 @@ public class Verify { assertTrue("Archive not a file", this.file.isFile()); ZipFile zipFile = new ZipFile(this.file); - Enumeration entries = zipFile.entries(); - Map zipMap = new HashMap(); - while (entries.hasMoreElements()) { - ZipEntry zipEntry = entries.nextElement(); - zipMap.put(zipEntry.getName(), zipEntry); + try { + ArchiveVerifier verifier = new ArchiveVerifier(zipFile); + verifyZipEntries(verifier); + } + finally { + zipFile.close(); } - verifyZipEntries(zipFile, zipMap); - zipFile.close(); } - protected void verifyZipEntries(ZipFile zipFile, Map entries) + protected void verifyZipEntries(ArchiveVerifier verifier) throws Exception { - verifyManifest(zipFile, entries.get("META-INF/MANIFEST.MF")); + verifyManifest(verifier); } - private void verifyManifest(ZipFile zipFile, ZipEntry zipEntry) throws Exception { - Manifest manifest = new Manifest(zipFile.getInputStream(zipEntry)); + private void verifyManifest(ArchiveVerifier verifier) throws Exception { + Manifest manifest = new Manifest(verifier.getEntryContent("META-INF/MANIFEST.MF")); verifyManifest(manifest); } protected abstract void verifyManifest(Manifest manifest) throws Exception; - protected final void assertHasEntryNameStartingWith( - Map entries, String value) { - for (String name : entries.keySet()) { - if (name.startsWith(value)) { - return; - } - } - throw new IllegalStateException("Expected entry starting with " + value); - } } - private static class JarArchiveVerification extends AbstractArchiveVerification { + public static class JarArchiveVerification extends AbstractArchiveVerification { private final String main; @@ -106,15 +151,15 @@ public class Verify { } @Override - protected void verifyZipEntries(ZipFile zipFile, Map entries) + protected void verifyZipEntries(ArchiveVerifier verifier) throws Exception { - super.verifyZipEntries(zipFile, entries); - assertHasEntryNameStartingWith(entries, "lib/spring-context"); - assertHasEntryNameStartingWith(entries, "lib/spring-core"); - assertHasEntryNameStartingWith(entries, "lib/javax.servlet-api-3.0.1.jar"); - assertTrue("Unpacked launcher classes", entries.containsKey("org/" + super.verifyZipEntries(verifier); + verifier.assertHasEntryNameStartingWith("lib/spring-context"); + verifier.assertHasEntryNameStartingWith("lib/spring-core"); + verifier.assertHasEntryNameStartingWith("lib/javax.servlet-api-3.0.1.jar"); + assertTrue("Unpacked launcher classes", verifier.hasEntry("org/" + "springframework/boot/loader/JarLauncher.class")); - assertTrue("Own classes", entries.containsKey("org/" + assertTrue("Own classes", verifier.hasEntry("org/" + "test/SampleApplication.class")); } @@ -127,25 +172,25 @@ public class Verify { } } - private static class WarArchiveVerification extends AbstractArchiveVerification { + public static class WarArchiveVerification extends AbstractArchiveVerification { public WarArchiveVerification(File file) { super(file); } @Override - protected void verifyZipEntries(ZipFile zipFile, Map entries) + protected void verifyZipEntries(ArchiveVerifier verifier) throws Exception { - super.verifyZipEntries(zipFile, entries); - assertHasEntryNameStartingWith(entries, "WEB-INF/lib/spring-context"); - assertHasEntryNameStartingWith(entries, "WEB-INF/lib/spring-core"); - assertHasEntryNameStartingWith(entries, + super.verifyZipEntries(verifier); + verifier.assertHasEntryNameStartingWith("WEB-INF/lib/spring-context"); + verifier.assertHasEntryNameStartingWith("WEB-INF/lib/spring-core"); + verifier.assertHasEntryNameStartingWith( "WEB-INF/lib-provided/javax.servlet-api-3.0.1.jar"); - assertTrue("Unpacked launcher classes", entries.containsKey("org/" + assertTrue("Unpacked launcher classes", verifier.hasEntry("org/" + "springframework/boot/loader/JarLauncher.class")); - assertTrue("Own classes", entries.containsKey("WEB-INF/classes/org/" + assertTrue("Own classes", verifier.hasEntry("WEB-INF/classes/org/" + "test/SampleApplication.class")); - assertTrue("Web content", entries.containsKey("index.html")); + assertTrue("Web content", verifier.hasEntry("index.html")); } @Override