diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/EmbeddedDatabaseConnection.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/EmbeddedDatabaseConnection.java index d8c04948788..f91cf1c86dc 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/EmbeddedDatabaseConnection.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/EmbeddedDatabaseConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * 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. @@ -119,36 +119,13 @@ public enum EmbeddedDatabaseConnection { * @return true if the data sourceis one of the embedded types */ public static boolean isEmbedded(DataSource dataSource) { - boolean embedded = false; try { - embedded = new JdbcTemplate(dataSource) - .execute(new ConnectionCallback() { - @Override - public Boolean doInConnection(Connection con) - throws SQLException, DataAccessException { - String productName = con.getMetaData() - .getDatabaseProductName(); - if (productName == null) { - return false; - } - productName = productName.toUpperCase(); - if (productName.contains(H2.name())) { - return true; - } - if (productName.contains(HSQL.name())) { - return true; - } - if (productName.contains(DERBY.name())) { - return true; - } - return false; - } - }); + return new JdbcTemplate(dataSource).execute(new IsEmbedded()); } - catch (DataAccessException e) { + catch (DataAccessException ex) { // Could not connect, which means it's not embedded + return false; } - return embedded; } /** @@ -170,4 +147,27 @@ public enum EmbeddedDatabaseConnection { return NONE; } + /** + * {@link ConnectionCallback} to determine if a connection is embedded. + */ + private static class IsEmbedded implements ConnectionCallback { + + @Override + public Boolean doInConnection(Connection connection) throws SQLException, + DataAccessException { + String productName = connection.getMetaData().getDatabaseProductName(); + if (productName == null) { + return false; + } + productName = productName.toUpperCase(); + EmbeddedDatabaseConnection[] candidates = EmbeddedDatabaseConnection.values(); + for (EmbeddedDatabaseConnection candidate : candidates) { + if (candidate != NONE && productName.contains(candidate.name())) { + return true; + } + } + return false; + } + + } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java index eb9ab4268b9..3dfaca207e5 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/JmsTemplateAutoConfiguration.java @@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.core.JmsTemplate; +import org.springframework.util.StringUtils; /** * {@link EnableAutoConfiguration Auto-configuration} for {@link JmsTemplate}. @@ -64,25 +65,22 @@ public class JmsTemplateAutoConfiguration { @Bean public ConnectionFactory jmsConnectionFactory() { - ConnectionFactory connectionFactory; - if (this.config.getUser() != null && !"".equals(this.config.getUser()) - && this.config.getPassword() != null - && !"".equals(this.config.getPassword())) { - connectionFactory = new ActiveMQConnectionFactory(this.config.getUser(), - this.config.getPassword(), this.config.getBrokerUrl()); - } - else { - connectionFactory = new ActiveMQConnectionFactory( - this.config.getBrokerUrl()); - } + ConnectionFactory connectionFactory = getActiveMQConnectionFactory(); if (this.config.isPooled()) { PooledConnectionFactory pool = new PooledConnectionFactory(); pool.setConnectionFactory(connectionFactory); return pool; } - else { - return connectionFactory; + return connectionFactory; + } + + private ConnectionFactory getActiveMQConnectionFactory() { + if (StringUtils.hasLength(this.config.getUser()) + && StringUtils.hasLength(this.config.getPassword())) { + return new ActiveMQConnectionFactory(this.config.getUser(), + this.config.getPassword(), this.config.getBrokerUrl()); } + return new ActiveMQConnectionFactory(this.config.getBrokerUrl()); } } diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 2eb58d01dd0..ea480c437e7 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -935,14 +935,14 @@ and {sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[`JpaBas for more details. + [[howto-use-custom-entity-manager]] === Use a custom EntityManagerFactory -To take full control of the configuration of the -`EntityManagerFactory`, you need to add a `@Bean` named -"entityManagerFactory". To avoid eager initialization of JPA -infrastructure Spring Boot autoconfiguration does not switch on its -entity manager based on the presence of a bean of that type. Instead -it has to do it by name. +To take full control of the configuration of the `EntityManagerFactory`, you need to add +a `@Bean` named "entityManagerFactory". To avoid eager initialization of JPA +infrastructure, Spring Boot auto-configuration does not switch on its entity manager +based on the presence of a bean of that type. Instead it has to do it by name. + [[howto-use-traditional-persistence-xml]] @@ -1140,9 +1140,12 @@ use this in a webapp is to inject it into a void method in a } ---- -You will get the best results if you put this in a nested class, or a standalone class (i.e. -not mixed in with a lot of other `@Beans` that might be allowed to influence the order of -instantiation). The https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-secure[secure web sample] is a useful template to follow. +You will get the best results if you put this in a nested class, or a standalone class +(i.e. not mixed in with a lot of other `@Beans` that might be allowed to influence the +order of instantiation). The {github-code}/spring-boot-samples/spring-boot-sample-web-secure[secure web sample] +is a useful template to follow. + + [[howto-enable-https]] === Enable HTTPS diff --git a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 204925852de..3fb6d7c3c13 100644 --- a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -251,8 +251,8 @@ all non-sensitive endpoints to be exposed over HTTP. The default convention is t [[production-ready-sensitive-endpoints]] === Exposing sensitive endpoints -If you use ``Spring Security'' sensitive endpoints will be exposed over HTTP, but also -protected. By default ``basic'' authentication will be used with the username `user` +If you use ``Spring Security'' sensitive endpoints will be exposed over HTTP, but also +protected. By default ``basic'' authentication will be used with the username `user` and a generated password (which is printed on the console when the application starts). TIP: Generated passwords are logged as the application starts. Search for ``Using default @@ -300,11 +300,10 @@ The `management.port` property can be used to change the HTTP port. management.port=8081 ---- -Since your management -port is often protected by a firewall, and not exposed to the public you might not need -security on the management endpoints, even if your main application is secure. In that -case you will have Spring -Security on the classpath, and you can disable management security like this: +Since your management port is often protected by a firewall, and not exposed to the public +you might not need security on the management endpoints, even if your main application is +secure. In that case you will have Spring Security on the classpath, and you can disable +management security like this: [source,properties,indent=0] ---- @@ -314,6 +313,8 @@ Security on the classpath, and you can disable management security like this: (If you don't have Spring Security on the classpath then there is no need to explicitly disable the management security in this way, and it might even break the application.) + + [[production-ready-customizing-management-server-address]] === Customizing the management server address You can customize the address that the management endpoints are available on by diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index e007e3a7023..15276c8eddb 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -993,6 +993,8 @@ packaged as an executable archive), there are some limitations in the JSP suppor There is a {github-code}/spring-boot-samples/spring-boot-sample-web-jsp[JSP sample] so you can see how to set things up. + + [[boot-features-security]] == Security If Spring Security is on the classpath then web applications will be secure by default @@ -1001,58 +1003,47 @@ application you can also add `@EnableGlobalMethodSecurity` with your desired set Additional information can be found in the {spring-security-reference}#jc-method[Spring Security Reference]. -The default `AuthenticationManager` has a single user (username -``user'' and password random, printed at INFO level when the -application starts up). You can change the password by providing a -`security.user.password`. This and other useful properties are -externalized via -{sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[`SecurityProperties`] +The default `AuthenticationManager` has a single user (username ``user'' and password +random, printed at INFO level when the application starts up). You can change the +password by providing a `security.user.password`. This and other useful properties are +externalized via {sc-spring-boot-autoconfigure}/security/SecurityProperties.{sc-ext}[`SecurityProperties`] (properties prefix "security"). -The default security configuration is implemented in -`SecurityAutoConfiguration` and in the classes imported from there -(`SpringBootWebSecurityConfiguration` for web security and -`AuthenticationManagerConfiguration` for authentication configuration -which is also relevant in non-web applications). To switch off the -Boot default configuration completely in a web application you can add -a bean with `@EnableWebSecurity`. To customize it you normally use -external properties and beans of type `WebConfigurerAdapter` (e.g. to +The default security configuration is implemented in `SecurityAutoConfiguration` and in +the classes imported from there (`SpringBootWebSecurityConfiguration` for web security +and `AuthenticationManagerConfiguration` for authentication configuration which is also +relevant in non-web applications). To switch off the Boot default configuration +completely in a web application you can add a bean with `@EnableWebSecurity`. To customize +it you normally use external properties and beans of type `WebConfigurerAdapter` (e.g. to add form-based login). There are several secure applications in the -{github-code}/spring-boot-samples/[Spring Boot samples] to get you -started with common use cases. - -The basic features you get out of the box in a web application are - -* An `AuthenticationManager` bean with in-memory store and a single - user (see `SecurityProperties.User` for the properties of the user). +{github-code}/spring-boot-samples/[Spring Boot samples] to get you started with common +use cases. -* Ignored (unsecure) paths for common static resource locations - (`/css/**`, `/js/**`, `/images/**` and `**/favicon.ico`). +The basic features you get out of the box in a web application are: +* An `AuthenticationManager` bean with in-memory store and a single user (see + `SecurityProperties.User` for the properties of the user). +* Ignored (unsecure) paths for common static resource locations (`/css/**`, `/js/**`, + `/images/**` and `**/favicon.ico`). * HTTP Basic security for all other endpoints. +* Security events published to Spring's `ApplicationEventPublisher` (successful and + unsuccessful authentication and access denied). +* Common low-level features (HSTS, XSS, CSRF, caching) provided by Spring Security are + on by default. -* Security events published to Spring's `ApplicationEventPublisher` - (successful and unsuccessful authentication and access denied). - -* Common low-level features (HSTS, XSS, CSRF, caching) provided by Spring -Security are on by default. - -All of the above can be switched on and off or modified using external -properties (`security.*`). +All of the above can be switched on and off or modified using external properties +(`security.*`). If the Actuator is also in use, you will find: -* The management endpoints are secure even if the application - endpoints are unsecure. +* The management endpoints are secure even if the application endpoints are unsecure. +* Security events are transformed into `AuditEvents` and published to the `AuditService`. +* The default user will have the "ADMIN" role as well as the "USER" role. -* Security events are transformed into `AuditEvents` and published to - the `AuditService`. +The Actuator security features can be modified using external properties +(`management.security.*`). -* The default user will have the "ADMIN" role as well as the "USER" - role. -The Actuator security features can be modified using external -properties (`management.security.*`). [[boot-features-sql]] == Working with SQL databases @@ -1299,12 +1290,12 @@ following to your `application.properties`. spring.jpa.hibernate.ddl-auto=create-drop ---- -Note that Hibernate's own internal property name for this (if you -happen to remember it better) is `hibernate.hbm2ddl.auto`. You can set -it, along with other Hibernate native properties, using -`spring.jpa.properties.*` (the prefix is stripped before adding them -to the entity manager). Also relevant: -`spring.jpa.generate-ddl=false` switches off all DDL generation. +NOTE: Hibernate's own internal property name for this (if you happen to remember it +better) is `hibernate.hbm2ddl.auto`. You can set it, along with other Hibernate native +properties, using `spring.jpa.properties.*` (the prefix is stripped before adding them +to the entity manager). Alternatively, `spring.jpa.generate-ddl=false` switches off all +DDL generation. + [[boot-features-nosql]] diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/RunApp.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/RunApp.java index d2e7387bff9..5f873bf46ba 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/RunApp.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/task/RunApp.java @@ -35,7 +35,7 @@ import org.springframework.boot.loader.tools.MainClassFinder; /** * Run the project from Gradle. - * + * * @author Dave Syer */ public class RunApp extends DefaultTask { @@ -75,7 +75,7 @@ public class RunApp extends DefaultTask { } if (outputDir != null) { for (File directory : allResources) { - FileUtils.removeDuplicatesFromCopy(outputDir, directory); + FileUtils.removeDuplicatesFromOutputDirectory(outputDir, directory); } } exec.exec(); diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java index 116f86d9e0d..cdf1d543f58 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/FileUtils.java @@ -1,9 +1,9 @@ /* - * originright 2012-2013 the copyal author or authors. + * 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 origin of the License at + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -26,24 +26,24 @@ import java.io.File; public class FileUtils { /** - * Utility to remove duplicate files from a "copy" directory if they already exist in - * an "origin". Recursively scans the origin directory looking for files (not + * Utility to remove duplicate files from an "output" directory if they already exist + * in an "origin". Recursively scans the origin directory looking for files (not * directories) that exist in both places and deleting the copy. - * - * @param copy the copy directory - * @param origin the origin directory + * @param outputDirectory the output directory + * @param originDirectory the origin directory */ - public static void removeDuplicatesFromCopy(File copy, File origin) { - if (origin.isDirectory()) { - for (String name : origin.list()) { - File targetFile = new File(copy, name); + public static void removeDuplicatesFromOutputDirectory(File outputDirectory, + File originDirectory) { + if (originDirectory.isDirectory()) { + for (String name : originDirectory.list()) { + File targetFile = new File(outputDirectory, name); if (targetFile.exists() && targetFile.canWrite()) { if (!targetFile.isDirectory()) { targetFile.delete(); } else { - FileUtils.removeDuplicatesFromCopy(targetFile, new File(origin, - name)); + FileUtils.removeDuplicatesFromOutputDirectory(targetFile, + new File(originDirectory, name)); } } } diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/FileUtilsTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/FileUtilsTests.java index e435bf29623..475f16e2a22 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/FileUtilsTests.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/FileUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * 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. @@ -27,60 +27,67 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** + * Tests fir {@link FileUtils}. + * * @author Dave Syer */ public class FileUtilsTests { - private File origin; - private File target; + private File outputDirectory; + + private File originDirectory; @Before public void init() { - this.origin = new File("target/test/remove"); - this.target = new File("target/test/keep"); - FileSystemUtils.deleteRecursively(this.origin); - FileSystemUtils.deleteRecursively(this.target); - this.origin.mkdirs(); - this.target.mkdirs(); + this.outputDirectory = new File("target/test/remove"); + this.originDirectory = new File("target/test/keep"); + FileSystemUtils.deleteRecursively(this.outputDirectory); + FileSystemUtils.deleteRecursively(this.originDirectory); + this.outputDirectory.mkdirs(); + this.originDirectory.mkdirs(); } @Test public void simpleDuplicateFile() throws IOException { - File file = new File(this.origin, "logback.xml"); + File file = new File(this.outputDirectory, "logback.xml"); file.createNewFile(); - new File(this.target, "logback.xml").createNewFile(); - FileUtils.removeDuplicatesFromCopy(this.origin, this.target); + new File(this.originDirectory, "logback.xml").createNewFile(); + FileUtils.removeDuplicatesFromOutputDirectory(this.outputDirectory, + this.originDirectory); assertFalse(file.exists()); } @Test public void nestedDuplicateFile() throws IOException { - assertTrue(new File(this.origin, "sub").mkdirs()); - assertTrue(new File(this.target, "sub").mkdirs()); - File file = new File(this.origin, "sub/logback.xml"); + assertTrue(new File(this.outputDirectory, "sub").mkdirs()); + assertTrue(new File(this.originDirectory, "sub").mkdirs()); + File file = new File(this.outputDirectory, "sub/logback.xml"); file.createNewFile(); - new File(this.target, "sub/logback.xml").createNewFile(); - FileUtils.removeDuplicatesFromCopy(this.origin, this.target); + new File(this.originDirectory, "sub/logback.xml").createNewFile(); + FileUtils.removeDuplicatesFromOutputDirectory(this.outputDirectory, + this.originDirectory); assertFalse(file.exists()); } @Test public void nestedNonDuplicateFile() throws IOException { - assertTrue(new File(this.origin, "sub").mkdirs()); - assertTrue(new File(this.target, "sub").mkdirs()); - File file = new File(this.origin, "sub/logback.xml"); + assertTrue(new File(this.outputDirectory, "sub").mkdirs()); + assertTrue(new File(this.originDirectory, "sub").mkdirs()); + File file = new File(this.outputDirectory, "sub/logback.xml"); file.createNewFile(); - new File(this.target, "sub/different.xml").createNewFile(); - FileUtils.removeDuplicatesFromCopy(this.origin, this.target); + new File(this.originDirectory, "sub/different.xml").createNewFile(); + FileUtils.removeDuplicatesFromOutputDirectory(this.outputDirectory, + this.originDirectory); assertTrue(file.exists()); } @Test public void nonDuplicateFile() throws IOException { - File file = new File(this.origin, "logback.xml"); + File file = new File(this.outputDirectory, "logback.xml"); file.createNewFile(); - new File(this.target, "different.xml").createNewFile(); - FileUtils.removeDuplicatesFromCopy(this.origin, this.target); + new File(this.originDirectory, "different.xml").createNewFile(); + FileUtils.removeDuplicatesFromOutputDirectory(this.outputDirectory, + this.originDirectory); assertTrue(file.exists()); } 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 27ee4f53b40..f44a61393bb 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 @@ -198,7 +198,7 @@ public class RunMojo extends AbstractMojo { for (Resource resource : this.project.getResources()) { File directory = new File(resource.getDirectory()); urls.add(directory.toURI().toURL()); - FileUtils.removeDuplicatesFromCopy(this.classesDirectory, directory); + FileUtils.removeDuplicatesFromOutputDirectory(this.classesDirectory, directory); } } } 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 fff1256f491..853de0d83a5 100644 --- a/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java +++ b/spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * 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.