Merge branch '1.5.x'

This commit is contained in:
Phillip Webb
2016-10-31 23:13:37 -07:00
33 changed files with 527 additions and 560 deletions

View File

@@ -96,8 +96,8 @@ class TypeUtils {
/**
* Return the qualified name of the specified element.
* @param element the element to handle
* @return the fully qualified name of the element, suitable for a call
* to {@link Class#forName(String)}
* @return the fully qualified name of the element, suitable for a call to
* {@link Class#forName(String)}
*/
public String getQualifiedName(Element element) {
if (element == null) {
@@ -106,19 +106,20 @@ class TypeUtils {
TypeElement enclosingElement = getEnclosingTypeElement(element.asType());
if (enclosingElement != null) {
return getQualifiedName(enclosingElement) + "$"
+ ((DeclaredType) element.asType()).asElement().getSimpleName().toString();
+ ((DeclaredType) element.asType()).asElement().getSimpleName()
.toString();
}
if (element instanceof TypeElement) {
return ((TypeElement) element).getQualifiedName().toString();
}
throw new IllegalStateException("Could not extract qualified name from "
+ element);
throw new IllegalStateException(
"Could not extract qualified name from " + element);
}
/**
* Return the type of the specified {@link TypeMirror} including all its generic
* information.
* @param type the type to handle
* @param type the type to handle
* @return a representation of the type including all its generic information
*/
public String getType(TypeMirror type) {

View File

@@ -404,8 +404,7 @@ public class ConfigurationMetadataAnnotationProcessorTests {
assertThat(metadata).has(Metadata.withGroup("generic.foo.bar.biz").ofType(
"org.springframework.boot.configurationsample.specific.GenericConfig$Bar$Biz"));
assertThat(metadata).has(Metadata.withProperty("generic.foo.name")
.ofType(String.class)
.fromSource(GenericConfig.Foo.class));
.ofType(String.class).fromSource(GenericConfig.Foo.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.string-to-bar")
.ofType("java.util.Map<java.lang.String,org.springframework.boot.configurationsample.specific.GenericConfig.Bar<java.lang.Integer>>")
.fromSource(GenericConfig.Foo.class));
@@ -413,11 +412,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
.ofType("java.util.Map<java.lang.String,java.lang.Integer>")
.fromSource(GenericConfig.Foo.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.name")
.ofType("java.lang.String")
.fromSource(GenericConfig.Bar.class));
.ofType("java.lang.String").fromSource(GenericConfig.Bar.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.biz.name")
.ofType("java.lang.String")
.fromSource(GenericConfig.Bar.Biz.class));
.ofType("java.lang.String").fromSource(GenericConfig.Bar.Biz.class));
assertThat(metadata.getItems()).hasSize(9);
}

View File

@@ -21,13 +21,12 @@ import java.util.Map;
import java.util.Set;
import groovy.lang.Closure;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPlugin;
import org.springframework.boot.gradle.buildinfo.BuildInfo;
import org.springframework.boot.loader.tools.Layout;
import org.springframework.boot.loader.tools.LayoutType;
import org.springframework.boot.loader.tools.Layouts;
/**
* Gradle DSL Extension for 'Spring Boot'. Most of the time Spring Boot can guess the
@@ -89,7 +88,7 @@ public class SpringBootPluginExtension {
* the MANIFEST.MF 'Main-Class' to be PropertiesLauncher. Gradle will coerce literal
* String values to the correct type.
*/
String layout;
LayoutType layout;
/**
* Libraries that must be unpacked from fat jars in order to run. Use Strings in the
@@ -146,7 +145,7 @@ public class SpringBootPluginExtension {
* @return the Layout to use or null if not explicitly set
*/
public Layout convertLayout() {
return (this.layout == null ? null : LayoutType.layout(this.layout));
return (this.layout == null ? null : this.layout.layout);
}
public String getMainClass() {
@@ -189,11 +188,11 @@ public class SpringBootPluginExtension {
this.backupSource = backupSource;
}
public String getLayout() {
public LayoutType getLayout() {
return this.layout;
}
public void setLayout(String layout) {
public void setLayout(LayoutType layout) {
this.layout = layout;
}
@@ -277,4 +276,29 @@ public class SpringBootPluginExtension {
}
}
/**
* Layout Types.
*/
enum LayoutType {
JAR(new Layouts.Jar()),
WAR(new Layouts.War()),
ZIP(new Layouts.Expanded()),
DIR(new Layouts.Expanded()),
MODULE(new Layouts.Module()),
NONE(new Layouts.None());
Layout layout;
LayoutType(Layout layout) {
this.layout = layout;
}
}
}

View File

@@ -51,6 +51,8 @@ import java.util.zip.ZipEntry;
*/
public class JarWriter {
private static final String NESTED_LOADER_JAR = "META-INF/loader/spring-boot-loader.jar";
private static final int BUFFER_SIZE = 32 * 1024;
private final JarOutputStream jarOutput;
@@ -201,20 +203,9 @@ public class JarWriter {
/**
* Write the required spring-boot-loader classes to the JAR.
* @throws IOException if the classes cannot be written
* @deprecated us {@link #writeLoaderClasses(String)} instead
*/
@Deprecated
public void writeLoaderClasses() throws IOException {
writeLoaderClasses(Layouts.DEFAULT_LOADER_JAR);
}
/**
* Write the required spring-boot-loader classes to the JAR.
* @param loaderJarPath the path to the loader jar (in the classpath)
* @throws IOException if the classes cannot be written
*/
public void writeLoaderClasses(String loaderJarPath) throws IOException {
URL loaderJar = getClass().getClassLoader().getResource(loaderJarPath);
URL loaderJar = getClass().getClassLoader().getResource(NESTED_LOADER_JAR);
JarInputStream inputStream = new JarInputStream(
new BufferedInputStream(loaderJar.openStream()));
JarEntry entry;

View File

@@ -40,25 +40,15 @@ public interface Layout {
String getLibraryDestination(String libraryName, LibraryScope scope);
/**
* Returns the location of classes within the archive. Empty if the location is the
* root path, otherwise ends with a slash ('/').
* Returns the location of classes within the archive.
* @return the classes location
*/
String getClassesLocation();
/**
* Returns if loader classes should be included to make the archive executable. If
* true, then {@link #getLoaderJarPath()} should point to a valid jar file that
* contains the loader classes.
* Returns if loader classes should be included to make the archive executable.
* @return if the layout is executable
*/
boolean isExecutable();
/**
* Returns the path to a nested jar that contains the loader, and which will be
* unpacked into the root of the repackaged jar.
* @return the path to a nested jar that contains the loader
*/
String getLoaderJarPath();
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2012-2015 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.tools;
/**
* Strategy for creating instances of {@link Layout}.
*
* @author Dave Syer
*
*/
public interface LayoutFactory {
Layout getLayout();
String getName();
}

View File

@@ -1,101 +0,0 @@
/*
* Copyright 2012-2015 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.tools;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.core.io.support.SpringFactoriesLoader;
/**
* Archive layout types.
*
* @author Dave Syer
*/
public enum LayoutType {
/**
* Jar Layout.
*/
JAR(new Layouts.Jar()),
/**
* War Layout.
*/
WAR(new Layouts.War()),
/**
* Zip Layout.
*/
ZIP(new Layouts.Expanded()),
/**
* Dir Layout.
*/
DIR(new Layouts.Expanded()),
/**
* Module Layout.
*/
MODULE(new Layouts.Module()),
/**
* No Layout.
*/
NONE(new Layouts.None());
private static Map<String, Layout> customTypes;
private final Layout layout;
public Layout layout() {
return this.layout;
}
LayoutType(Layout layout) {
this.layout = layout;
}
public static Layout layout(String value) {
try {
return valueOf(value).layout();
}
catch (IllegalArgumentException e) {
if (customTypes == null) {
customTypes = new HashMap<String, Layout>();
lookupCustomTypes();
}
Layout layout = customTypes.get(value);
if (layout == null) {
throw new IllegalArgumentException(
"Cannot resolve custom layout type: " + value);
}
return layout;
}
}
private static void lookupCustomTypes() {
ClassLoader classLoader = LayoutType.class.getClassLoader();
List<LayoutFactory> factories = SpringFactoriesLoader
.loadFactories(LayoutFactory.class, classLoader);
for (LayoutFactory factory : factories) {
customTypes.put(factory.getName(), factory.getLayout());
}
}
}

View File

@@ -33,11 +33,6 @@ import java.util.Set;
*/
public final class Layouts {
/**
* Default value for {@link Layout#getLoaderJarPath()}.
*/
public static final String DEFAULT_LOADER_JAR = "META-INF/loader/spring-boot-loader.jar";
private Layouts() {
}
@@ -92,11 +87,6 @@ public final class Layouts {
return true;
}
@Override
public String getLoaderJarPath() {
return DEFAULT_LOADER_JAR;
}
}
/**
@@ -126,11 +116,6 @@ public final class Layouts {
return false;
}
@Override
public String getLoaderJarPath() {
return DEFAULT_LOADER_JAR;
}
}
/**
@@ -169,11 +154,6 @@ public final class Layouts {
return true;
}
@Override
public String getLoaderJarPath() {
return DEFAULT_LOADER_JAR;
}
}
/**
@@ -208,11 +188,6 @@ public final class Layouts {
return false;
}
@Override
public String getLoaderJarPath() {
return DEFAULT_LOADER_JAR;
}
}
}

View File

@@ -216,7 +216,7 @@ public class Repackager {
}
writeNestedLibraries(standardLibraries, seen, writer);
if (this.layout.isExecutable()) {
writer.writeLoaderClasses(this.layout.getLoaderJarPath());
writer.writeLoaderClasses();
}
}
finally {

View File

@@ -1,53 +0,0 @@
/*
* Copyright 2012-2015 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.tools;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
*
*/
public class LayoutTypeTests {
@Test
public void standardType() {
assertThat(LayoutType.layout("DIR"))
.isEqualTo(LayoutType.valueOf("DIR").layout());
}
@Test
public void customType() {
assertThat(LayoutType.layout("CUSTOM")).isNotNull();
}
public static class TestLayoutFactory implements LayoutFactory {
@Override
public Layout getLayout() {
return new Layouts.Jar();
}
@Override
public String getName() {
return "CUSTOM";
}
}
}

View File

@@ -1,2 +0,0 @@
org.springframework.boot.loader.tools.LayoutFactory=\
org.springframework.boot.loader.tools.LayoutTypeTests.TestLayoutFactory

View File

@@ -371,6 +371,10 @@ public class JarFile extends java.util.jar.JarFile {
return this.pathFromRoot;
}
JarFileType getType() {
return this.type;
}
/**
* Register a {@literal 'java.protocol.handler.pkgs'} property so that a
* {@link URLStreamHandler} will be located to deal with jar URLs.
@@ -396,7 +400,10 @@ public class JarFile extends java.util.jar.JarFile {
}
}
private enum JarFileType {
/**
* The type of a {@link JarFile}.
*/
enum JarFileType {
DIRECT, NESTED_DIRECTORY, NESTED_JAR
}

View File

@@ -29,6 +29,8 @@ import java.net.URLEncoder;
import java.net.URLStreamHandler;
import java.security.Permission;
import org.springframework.boot.loader.data.RandomAccessData.ResourceAccess;
/**
* {@link java.net.JarURLConnection} used to support {@link JarFile#getUrl()}.
*
@@ -160,11 +162,14 @@ final class JarURLConnection extends java.net.JarURLConnection {
if (this.jarFile == null) {
throw FILE_NOT_FOUND_EXCEPTION;
}
if (this.jarEntryName.isEmpty()) {
if (this.jarEntryName.isEmpty()
&& this.jarFile.getType() == JarFile.JarFileType.DIRECT) {
throw new IOException("no entry name specified");
}
connect();
InputStream inputStream = this.jarFile.getInputStream(this.jarEntry);
InputStream inputStream = (this.jarEntryName.isEmpty()
? this.jarFile.getData().getInputStream(ResourceAccess.ONCE)
: this.jarFile.getInputStream(this.jarEntry));
if (inputStream == null) {
throwFileNotFound(this.jarEntryName, this.jarFile);
}

View File

@@ -28,6 +28,7 @@ import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
@@ -54,6 +55,7 @@ import static org.mockito.Mockito.verify;
* @author Andy Wilkinson
*/
public class JarFileTests {
private static final String PROTOCOL_HANDLER = "java.protocol.handler.pkgs";
private static final String HANDLERS_PACKAGE = "org.springframework.boot.loader";
@@ -270,6 +272,12 @@ public class JarFileTests {
assertThat(conn.getJarFile()).isSameAs(nestedJarFile);
assertThat(conn.getJarFileURL().toString())
.isEqualTo("jar:" + this.rootJarFile.toURI() + "!/nested.jar");
assertThat(conn.getInputStream()).isNotNull();
JarInputStream jarInputStream = new JarInputStream(conn.getInputStream());
assertThat(jarInputStream.getNextJarEntry().getName()).isEqualTo("3.dat");
assertThat(jarInputStream.getNextJarEntry().getName()).isEqualTo("4.dat");
assertThat(jarInputStream.getNextJarEntry().getName()).isEqualTo("\u00E4.dat");
jarInputStream.close();
assertThat(conn.getPermission()).isInstanceOf(FilePermission.class);
FilePermission permission = (FilePermission) conn.getPermission();
assertThat(permission.getActions()).isEqualTo("read");

View File

@@ -42,7 +42,8 @@ import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
import org.springframework.boot.loader.tools.DefaultLaunchScript;
import org.springframework.boot.loader.tools.LaunchScript;
import org.springframework.boot.loader.tools.LayoutType;
import org.springframework.boot.loader.tools.Layout;
import org.springframework.boot.loader.tools.Layouts;
import org.springframework.boot.loader.tools.Libraries;
import org.springframework.boot.loader.tools.Repackager;
@@ -130,7 +131,7 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
* @since 1.0
*/
@Parameter
private String layout;
private LayoutType layout;
/**
* A list of the libraries that must be unpacked from fat jars in order to run.
@@ -227,7 +228,7 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
repackager.setMainClass(this.mainClass);
if (this.layout != null) {
getLog().info("Layout: " + this.layout);
repackager.setLayout(LayoutType.layout(this.layout));
repackager.setLayout(this.layout.layout());
}
return repackager;
}
@@ -308,6 +309,53 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
}
}
/**
* Archive layout types.
*/
public enum LayoutType {
/**
* Jar Layout.
*/
JAR(new Layouts.Jar()),
/**
* War Layout.
*/
WAR(new Layouts.War()),
/**
* Zip Layout.
*/
ZIP(new Layouts.Expanded()),
/**
* Dir Layout.
*/
DIR(new Layouts.Expanded()),
/**
* Module Layout.
*/
MODULE(new Layouts.Module()),
/**
* No Layout.
*/
NONE(new Layouts.None());
private final Layout layout;
public Layout layout() {
return this.layout;
}
LayoutType(Layout layout) {
this.layout = layout;
}
}
private static class LoggingRepackager extends Repackager {
private final Log log;

View File

@@ -1,57 +0,0 @@
-----
Use a custom layout
-----
Dave Syer
-----
2016-10-30
-----
Spring Boot repackages the jar file for this project using a custom
layout defined in the additional jar file, provided as a dependency
to the build plugin:
---
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<layout>CUSTOM</layout>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>custom-layout</artifactId>
<version>0.0.1.BUILD-SNAPSHOT</version>
</dependency>
</dependencies>
...
</plugin>
...
</plugins>
...
</build>
...
</project>
---
The layout is provided as an implementation of <<LayoutFactory>>
(from spring-boot-loader-tools) listed in
<<META-INF/spring-factories>> inside the <<custom-layout>> jar.

View File

@@ -48,8 +48,6 @@ Spring Boot Maven Plugin
* {{{./examples/repackage-disable-attach.html}Local repackaged artifact}}
* {{{./examples/custom-layout.html}Custom layout}}
* {{{./examples/exclude-dependency.html}Exclude a dependency}}
* {{{./examples/run-debug.html}Debug the application}}