From ed6f11d60de998f85687fa90a736b695771cf1a7 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 10 Jun 2016 11:46:26 -0700 Subject: [PATCH 1/4] Polish --- .../boot/autoconfigure/jdbc/DataSourceBuilder.java | 6 ++---- .../AbstractDevToolsDataSourceAutoConfigurationTests.java | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilder.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilder.java index d6a48e7f799..1e6b1ea67e2 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilder.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceBuilder.java @@ -83,10 +83,8 @@ public class DataSourceBuilder { private void bind(DataSource result) { MutablePropertyValues properties = new MutablePropertyValues(this.properties); - new RelaxedDataBinder(result) - .withAlias("url", "jdbcUrl") - .withAlias("username", "user") - .bind(properties); + new RelaxedDataBinder(result).withAlias("url", "jdbcUrl") + .withAlias("username", "user").bind(properties); } public DataSourceBuilder type(Class type) { diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java index 0d7a29c4541..a32d0747985 100644 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/AbstractDevToolsDataSourceAutoConfigurationTests.java @@ -76,7 +76,6 @@ public class AbstractDevToolsDataSourceAutoConfigurationTests { @Test public void emptyFactoryMethodMetadataIgnored() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - DataSource dataSource = mock(DataSource.class); AnnotatedGenericBeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition( dataSource.getClass()); From 1528764194aced9df27bc34847de70e0fcd0c268 Mon Sep 17 00:00:00 2001 From: Ivan Sopov Date: Fri, 10 Jun 2016 11:48:06 -0700 Subject: [PATCH 2/4] Fix potential offset errors in BasicJsonParser Update BasicJsonParser to fix potential exceptions if strings happen to be empty. Fixes gh-6136 --- .../java/org/springframework/boot/json/BasicJsonParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java b/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java index ec43e0cb454..9b0b40a3579 100644 --- a/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java +++ b/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java @@ -93,14 +93,14 @@ public class BasicJsonParser implements JsonParser { } private static String trimTrailingCharacter(String string, char c) { - if (string.length() >= 0 && string.charAt(string.length() - 1) == c) { + if (string.length() > 0 && string.charAt(string.length() - 1) == c) { return string.substring(0, string.length() - 1); } return string; } private static String trimLeadingCharacter(String string, char c) { - if (string.length() >= 0 && string.charAt(0) == c) { + if (string.length() > 0 && string.charAt(0) == c) { return string.substring(1); } return string; From a9b98cada5ef863b550770bb37dcba6f7af06c8f Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 10 Jun 2016 12:28:23 -0700 Subject: [PATCH 3/4] Allow loading from package names without dots Update BeanDefinitionLoader to support loading from package names that do not contain dots. Prior to this commit `new BeanDefinitionLoader(registry, "somepackage")` would fail because "somepackage" exists and is a resource but does not contain valid XML. Somewhat surprisingly the InputStream returned by the resource actually contains the listing of files in the package. Fixes gh-6126 --- .../boot/BeanDefinitionLoader.java | 25 ++++++++++++++++++- .../boot/BeanDefinitionLoaderTests.java | 11 ++++++++ .../MyComponentInPackageWithoutDot.java | 24 ++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 spring-boot/src/test/java/sampleconfig/MyComponentInPackageWithoutDot.java diff --git a/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java b/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java index 0c9aedb2a89..c394016f158 100644 --- a/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java +++ b/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java @@ -33,6 +33,7 @@ import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; @@ -201,7 +202,7 @@ class BeanDefinitionLoader { int loadCount = 0; boolean atLeastOneResourceExists = false; for (Resource resource : resources) { - if (resource != null && resource.exists()) { + if (isLoadCandidate(resource)) { atLeastOneResourceExists = true; loadCount += load(resource); } @@ -235,6 +236,28 @@ class BeanDefinitionLoader { } } + private boolean isLoadCandidate(Resource resource) { + if (resource == null || !resource.exists()) { + return false; + } + if (resource instanceof ClassPathResource) { + // A simple package without a '.' may accidentally get loaded as an XML + // document if we're not careful. The result of getInputStream() will be + // a file list of the package content. We double check here that it's not + // actually a package. + String path = ((ClassPathResource) resource).getPath(); + if (path.indexOf(".") == -1) { + try { + return Package.getPackage(path) == null; + } + catch (Exception ex) { + // Ignore + } + } + } + return true; + } + private Package findPackage(CharSequence source) { Package pkg = Package.getPackage(source.toString()); if (pkg != null) { diff --git a/spring-boot/src/test/java/org/springframework/boot/BeanDefinitionLoaderTests.java b/spring-boot/src/test/java/org/springframework/boot/BeanDefinitionLoaderTests.java index 12b21462798..c83cf3804d7 100644 --- a/spring-boot/src/test/java/org/springframework/boot/BeanDefinitionLoaderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/BeanDefinitionLoaderTests.java @@ -19,6 +19,7 @@ package org.springframework.boot; import org.junit.After; import org.junit.Before; import org.junit.Test; +import sampleconfig.MyComponentInPackageWithoutDot; import org.springframework.boot.sampleconfig.MyComponent; import org.springframework.context.support.StaticApplicationContext; @@ -134,6 +135,16 @@ public class BeanDefinitionLoaderTests { assertTrue(this.registry.containsBean("myComponent")); } + @Test + public void loadPackageNameWithoutDot() throws Exception { + // See gh-6126 + BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, + MyComponentInPackageWithoutDot.class.getPackage().getName()); + int loaded = loader.load(); + assertThat(loaded, equalTo(1)); + assertTrue(this.registry.containsBean("myComponentInPackageWithoutDot")); + } + @Test public void loadPackageAndClassDoesNotDoubleAdd() throws Exception { BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, diff --git a/spring-boot/src/test/java/sampleconfig/MyComponentInPackageWithoutDot.java b/spring-boot/src/test/java/sampleconfig/MyComponentInPackageWithoutDot.java new file mode 100644 index 00000000000..bba9fe2cff1 --- /dev/null +++ b/spring-boot/src/test/java/sampleconfig/MyComponentInPackageWithoutDot.java @@ -0,0 +1,24 @@ +/* + * 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 sampleconfig; + +import org.springframework.stereotype.Component; + +@Component +public class MyComponentInPackageWithoutDot { + +} From f27bdcb737ed74b101b8bc82fda02bc9e9eaf84f Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 10 Jun 2016 17:06:45 -0700 Subject: [PATCH 4/4] Prevent APT crashes on older Java versions Update TypeUtils to guard against the use of older Java versions. Both `Collection` and `Map` type lookups now fallback to generic free versions of the classes. Prior to this commit using `xmlbeans-maven-plugin` in combination with Spring Boot's annotation processor could result in `IllegalArgumentException: Incorrect number of type arguments`. Fixes gh-6122 --- .../configurationprocessor/TypeUtils.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java index c4d625eeb3f..59d02f551d7 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/TypeUtils.java @@ -27,7 +27,6 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; -import javax.lang.model.type.WildcardType; import javax.lang.model.util.Types; /** @@ -73,12 +72,25 @@ class TypeUtils { TypeUtils(ProcessingEnvironment env) { this.env = env; Types types = env.getTypeUtils(); - WildcardType wc = types.getWildcardType(null, null); - this.collectionType = types.getDeclaredType( - this.env.getElementUtils().getTypeElement(Collection.class.getName()), - wc); - this.mapType = types.getDeclaredType( - this.env.getElementUtils().getTypeElement(Map.class.getName()), wc, wc); + this.collectionType = getDeclaredType(types, Collection.class, 1); + this.mapType = getDeclaredType(types, Map.class, 2); + } + + private TypeMirror getDeclaredType(Types types, Class typeClass, + int numberOfTypeArgs) { + TypeMirror[] typeArgs = new TypeMirror[numberOfTypeArgs]; + for (int i = 0; i < typeArgs.length; i++) { + typeArgs[i] = types.getWildcardType(null, null); + } + TypeElement typeElement = this.env.getElementUtils() + .getTypeElement(typeClass.getName()); + try { + return types.getDeclaredType(typeElement, typeArgs); + } + catch (IllegalArgumentException ex) { + // Try again without generics for older Java versions + return types.getDeclaredType(typeElement); + } } public String getType(Element element) {