Commit 5b66ffbb authored by Phillip Webb's avatar Phillip Webb

Merge branch '1.4.x' into 1.5.x

parents f4328b41 cecc1c88
...@@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.mvc; ...@@ -19,6 +19,7 @@ package org.springframework.boot.actuate.endpoint.mvc;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -82,7 +83,8 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint { ...@@ -82,7 +83,8 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint {
} }
resource = null; resource = null;
} }
new Handler(resource).handleRequest(request, response); Handler handler = new Handler(resource, request.getServletContext());
handler.handleRequest(request, response);
} }
private Resource getLogFileResource() { private Resource getLogFileResource() {
...@@ -104,10 +106,11 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint { ...@@ -104,10 +106,11 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint {
private final Resource resource; private final Resource resource;
Handler(Resource resource) { Handler(Resource resource, ServletContext servletContext) {
this.resource = resource; this.resource = resource;
getLocations().add(resource); getLocations().add(resource);
try { try {
setServletContext(servletContext);
afterPropertiesSet(); afterPropertiesSet();
} }
catch (Exception ex) { catch (Exception ex) {
......
...@@ -16,16 +16,12 @@ ...@@ -16,16 +16,12 @@
package org.springframework.boot.autoconfigure.orm.jpa; package org.springframework.boot.autoconfigure.orm.jpa;
import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
...@@ -53,7 +49,6 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; ...@@ -53,7 +49,6 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
...@@ -69,8 +64,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter ...@@ -69,8 +64,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Import(DataSourceInitializedPublisher.Registrar.class) @Import(DataSourceInitializedPublisher.Registrar.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware { public abstract class JpaBaseConfiguration implements BeanFactoryAware {
private static final Log logger = LogFactory.getLog(JpaBaseConfiguration.class);
private final DataSource dataSource; private final DataSource dataSource;
private final JpaProperties properties; private final JpaProperties properties;
...@@ -110,8 +103,7 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ...@@ -110,8 +103,7 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider) { ObjectProvider<PersistenceUnitManager> persistenceUnitManagerProvider) {
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder( EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
jpaVendorAdapter, this.properties.getProperties(), jpaVendorAdapter, this.properties.getProperties(),
persistenceUnitManagerProvider.getIfAvailable(), persistenceUnitManagerProvider.getIfAvailable());
determinePersistenceUnitRootLocation());
builder.setCallback(getVendorCallback()); builder.setCallback(getVendorCallback());
return builder; return builder;
} }
...@@ -190,19 +182,6 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { ...@@ -190,19 +182,6 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
} }
private URL determinePersistenceUnitRootLocation() {
Class<?> source = getClass();
try {
URL url = source.getProtectionDomain().getCodeSource().getLocation();
return ResourceUtils.extractJarFileURL(url);
}
catch (Exception ex) {
logger.info("Could not determine persistence " + "unit root location from "
+ source + " : " + ex);
}
return null;
}
@Configuration @Configuration
@ConditionalOnWebApplication @ConditionalOnWebApplication
@ConditionalOnClass(WebMvcConfigurerAdapter.class) @ConditionalOnClass(WebMvcConfigurerAdapter.class)
......
...@@ -21,10 +21,13 @@ import java.util.HashMap; ...@@ -21,10 +21,13 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.devtools.restart.Restarter;
import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
...@@ -59,7 +62,7 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro ...@@ -59,7 +62,7 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
@Override @Override
public void postProcessEnvironment(ConfigurableEnvironment environment, public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) { SpringApplication application) {
if (isLocalApplication(environment)) { if (isLocalApplication(environment) && canAddProperties(environment)) {
PropertySource<?> propertySource = new MapPropertySource("refresh", PropertySource<?> propertySource = new MapPropertySource("refresh",
PROPERTIES); PROPERTIES);
environment.getPropertySources().addLast(propertySource); environment.getPropertySources().addLast(propertySource);
...@@ -70,4 +73,24 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro ...@@ -70,4 +73,24 @@ public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostPro
return environment.getPropertySources().get("remoteUrl") == null; return environment.getPropertySources().get("remoteUrl") == null;
} }
private boolean canAddProperties(Environment environment) {
return isRestarterInitialized() || isRemoteRestartEnabled(environment);
}
private boolean isRestarterInitialized() {
try {
Restarter restarter = Restarter.getInstance();
return (restarter != null && restarter.getInitialUrls() != null);
}
catch (Exception ex) {
return false;
}
}
private boolean isRemoteRestartEnabled(Environment environment) {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment,
"spring.devtools.remote.");
return resolver.containsProperty("secret");
}
} }
...@@ -16,11 +16,20 @@ ...@@ -16,11 +16,20 @@
package org.springframework.boot.devtools.env; package org.springframework.boot.devtools.env;
import java.net.URL;
import java.util.Collections;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.devtools.restart.RestartInitializer;
import org.springframework.boot.devtools.restart.Restarter;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -32,13 +41,22 @@ import org.springframework.context.annotation.Configuration; ...@@ -32,13 +41,22 @@ import org.springframework.context.annotation.Configuration;
*/ */
public class DevToolPropertiesIntegrationTests { public class DevToolPropertiesIntegrationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private ConfigurableApplicationContext context; private ConfigurableApplicationContext context;
@Before
public void setup() {
Restarter.initialize(new String[] {}, false, new MockInitializer(), false);
}
@After @After
public void cleanup() { public void cleanup() {
if (this.context != null) { if (this.context != null) {
this.context.close(); this.context.close();
} }
Restarter.clearInstance();
} }
@Test @Test
...@@ -59,6 +77,33 @@ public class DevToolPropertiesIntegrationTests { ...@@ -59,6 +77,33 @@ public class DevToolPropertiesIntegrationTests {
this.context.getBean(MyBean.class); this.context.getBean(MyBean.class);
} }
@Test
public void postProcessWhenRestarterDisabledAndRemoteSecretNotSetShouldNotAddPropertySource()
throws Exception {
Restarter.clearInstance();
Restarter.disable();
SpringApplication application = new SpringApplication(
BeanConditionConfiguration.class);
application.setWebEnvironment(false);
this.context = application.run();
this.thrown.expect(NoSuchBeanDefinitionException.class);
this.context.getBean(MyBean.class);
}
@Test
public void postProcessWhenRestarterDisabledAndRemoteSecretSetShouldAddPropertySource()
throws Exception {
Restarter.clearInstance();
Restarter.disable();
SpringApplication application = new SpringApplication(
BeanConditionConfiguration.class);
application.setWebEnvironment(false);
application.setDefaultProperties(Collections.<String, Object>singletonMap(
"spring.devtools.remote.secret", "donttell"));
this.context = application.run();
this.context.getBean(MyBean.class);
}
@Configuration @Configuration
@ConditionalOnProperty("spring.h2.console.enabled") @ConditionalOnProperty("spring.h2.console.enabled")
static class ClassConditionConfiguration { static class ClassConditionConfiguration {
...@@ -79,4 +124,12 @@ public class DevToolPropertiesIntegrationTests { ...@@ -79,4 +124,12 @@ public class DevToolPropertiesIntegrationTests {
} }
static class MockInitializer implements RestartInitializer {
@Override
public URL[] getInitialUrls(Thread thread) {
return new URL[] {};
}
}
} }
...@@ -101,15 +101,20 @@ public class TestDatabaseAutoConfiguration { ...@@ -101,15 +101,20 @@ public class TestDatabaseAutoConfiguration {
ConfigurableListableBeanFactory beanFactory) { ConfigurableListableBeanFactory beanFactory) {
BeanDefinitionHolder holder = getDataSourceBeanDefinition(beanFactory); BeanDefinitionHolder holder = getDataSourceBeanDefinition(beanFactory);
if (holder != null) { if (holder != null) {
logger.info("Replacing '" + holder.getBeanName() String beanName = holder.getBeanName();
+ "' DataSource bean with embedded version"); boolean primary = holder.getBeanDefinition().isPrimary();
registry.registerBeanDefinition(holder.getBeanName(), logger.info("Replacing '" + beanName + "' DataSource bean with "
createEmbeddedBeanDefinition()); + (primary ? "primary " : "") + "embedded version");
registry.registerBeanDefinition(beanName,
createEmbeddedBeanDefinition(primary));
} }
} }
private BeanDefinition createEmbeddedBeanDefinition() { private BeanDefinition createEmbeddedBeanDefinition(boolean primary) {
return new RootBeanDefinition(EmbeddedDataSourceFactoryBean.class); BeanDefinition beanDefinition = new RootBeanDefinition(
EmbeddedDataSourceFactoryBean.class);
beanDefinition.setPrimary(primary);
return beanDefinition;
} }
private BeanDefinitionHolder getDataSourceBeanDefinition( private BeanDefinitionHolder getDataSourceBeanDefinition(
......
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link AutoConfigureTestDatabase} when there are multiple
* datasources.
*
* @author Greg Potter
*/
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase
public class AutoConfigureTestDatabaseWithMultipleDatasourcesIntegrationTests {
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void replacesDefinedDataSourceWithExplicit() throws Exception {
// Look that the datasource is replaced with an H2 DB.
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
assertThat(product).startsWith("H2");
}
@Configuration
@EnableAutoConfiguration
static class Config {
@Bean
@Primary
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL);
return builder.build();
}
@Bean
public DataSource secondaryDataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL);
return builder.build();
}
}
}
...@@ -96,8 +96,8 @@ class TypeUtils { ...@@ -96,8 +96,8 @@ class TypeUtils {
/** /**
* Return the qualified name of the specified element. * Return the qualified name of the specified element.
* @param element the element to handle * @param element the element to handle
* @return the fully qualified name of the element, suitable for a call * @return the fully qualified name of the element, suitable for a call to
* to {@link Class#forName(String)} * {@link Class#forName(String)}
*/ */
public String getQualifiedName(Element element) { public String getQualifiedName(Element element) {
if (element == null) { if (element == null) {
...@@ -106,19 +106,20 @@ class TypeUtils { ...@@ -106,19 +106,20 @@ class TypeUtils {
TypeElement enclosingElement = getEnclosingTypeElement(element.asType()); TypeElement enclosingElement = getEnclosingTypeElement(element.asType());
if (enclosingElement != null) { if (enclosingElement != null) {
return getQualifiedName(enclosingElement) + "$" return getQualifiedName(enclosingElement) + "$"
+ ((DeclaredType) element.asType()).asElement().getSimpleName().toString(); + ((DeclaredType) element.asType()).asElement().getSimpleName()
.toString();
} }
if (element instanceof TypeElement) { if (element instanceof TypeElement) {
return ((TypeElement) element).getQualifiedName().toString(); return ((TypeElement) element).getQualifiedName().toString();
} }
throw new IllegalStateException("Could not extract qualified name from " throw new IllegalStateException(
+ element); "Could not extract qualified name from " + element);
} }
/** /**
* Return the type of the specified {@link TypeMirror} including all its generic * Return the type of the specified {@link TypeMirror} including all its generic
* information. * information.
* @param type the type to handle * @param type the type to handle
* @return a representation of the type including all its generic information * @return a representation of the type including all its generic information
*/ */
public String getType(TypeMirror type) { public String getType(TypeMirror type) {
......
...@@ -404,8 +404,7 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -404,8 +404,7 @@ public class ConfigurationMetadataAnnotationProcessorTests {
assertThat(metadata).has(Metadata.withGroup("generic.foo.bar.biz").ofType( assertThat(metadata).has(Metadata.withGroup("generic.foo.bar.biz").ofType(
"org.springframework.boot.configurationsample.specific.GenericConfig$Bar$Biz")); "org.springframework.boot.configurationsample.specific.GenericConfig$Bar$Biz"));
assertThat(metadata).has(Metadata.withProperty("generic.foo.name") assertThat(metadata).has(Metadata.withProperty("generic.foo.name")
.ofType(String.class) .ofType(String.class).fromSource(GenericConfig.Foo.class));
.fromSource(GenericConfig.Foo.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.string-to-bar") 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>>") .ofType("java.util.Map<java.lang.String,org.springframework.boot.configurationsample.specific.GenericConfig.Bar<java.lang.Integer>>")
.fromSource(GenericConfig.Foo.class)); .fromSource(GenericConfig.Foo.class));
...@@ -413,11 +412,9 @@ public class ConfigurationMetadataAnnotationProcessorTests { ...@@ -413,11 +412,9 @@ public class ConfigurationMetadataAnnotationProcessorTests {
.ofType("java.util.Map<java.lang.String,java.lang.Integer>") .ofType("java.util.Map<java.lang.String,java.lang.Integer>")
.fromSource(GenericConfig.Foo.class)); .fromSource(GenericConfig.Foo.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.name") assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.name")
.ofType("java.lang.String") .ofType("java.lang.String").fromSource(GenericConfig.Bar.class));
.fromSource(GenericConfig.Bar.class));
assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.biz.name") assertThat(metadata).has(Metadata.withProperty("generic.foo.bar.biz.name")
.ofType("java.lang.String") .ofType("java.lang.String").fromSource(GenericConfig.Bar.Biz.class));
.fromSource(GenericConfig.Bar.Biz.class));
assertThat(metadata.getItems()).hasSize(9); assertThat(metadata.getItems()).hasSize(9);
} }
......
...@@ -371,6 +371,10 @@ public class JarFile extends java.util.jar.JarFile { ...@@ -371,6 +371,10 @@ public class JarFile extends java.util.jar.JarFile {
return this.pathFromRoot; return this.pathFromRoot;
} }
JarFileType getType() {
return this.type;
}
/** /**
* Register a {@literal 'java.protocol.handler.pkgs'} property so that a * Register a {@literal 'java.protocol.handler.pkgs'} property so that a
* {@link URLStreamHandler} will be located to deal with jar URLs. * {@link URLStreamHandler} will be located to deal with jar URLs.
...@@ -396,7 +400,10 @@ public class JarFile extends java.util.jar.JarFile { ...@@ -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 DIRECT, NESTED_DIRECTORY, NESTED_JAR
} }
......
...@@ -29,6 +29,8 @@ import java.net.URLEncoder; ...@@ -29,6 +29,8 @@ import java.net.URLEncoder;
import java.net.URLStreamHandler; import java.net.URLStreamHandler;
import java.security.Permission; import java.security.Permission;
import org.springframework.boot.loader.data.RandomAccessData.ResourceAccess;
/** /**
* {@link java.net.JarURLConnection} used to support {@link JarFile#getUrl()}. * {@link java.net.JarURLConnection} used to support {@link JarFile#getUrl()}.
* *
...@@ -160,11 +162,14 @@ final class JarURLConnection extends java.net.JarURLConnection { ...@@ -160,11 +162,14 @@ final class JarURLConnection extends java.net.JarURLConnection {
if (this.jarFile == null) { if (this.jarFile == null) {
throw FILE_NOT_FOUND_EXCEPTION; 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"); throw new IOException("no entry name specified");
} }
connect(); 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) { if (inputStream == null) {
throwFileNotFound(this.jarEntryName, this.jarFile); throwFileNotFound(this.jarEntryName, this.jarFile);
} }
......
...@@ -28,6 +28,7 @@ import java.net.URLClassLoader; ...@@ -28,6 +28,7 @@ import java.net.URLClassLoader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest; import java.util.jar.Manifest;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
...@@ -54,6 +55,7 @@ import static org.mockito.Mockito.verify; ...@@ -54,6 +55,7 @@ import static org.mockito.Mockito.verify;
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
public class JarFileTests { public class JarFileTests {
private static final String PROTOCOL_HANDLER = "java.protocol.handler.pkgs"; private static final String PROTOCOL_HANDLER = "java.protocol.handler.pkgs";
private static final String HANDLERS_PACKAGE = "org.springframework.boot.loader"; private static final String HANDLERS_PACKAGE = "org.springframework.boot.loader";
...@@ -270,6 +272,12 @@ public class JarFileTests { ...@@ -270,6 +272,12 @@ public class JarFileTests {
assertThat(conn.getJarFile()).isSameAs(nestedJarFile); assertThat(conn.getJarFile()).isSameAs(nestedJarFile);
assertThat(conn.getJarFileURL().toString()) assertThat(conn.getJarFileURL().toString())
.isEqualTo("jar:" + this.rootJarFile.toURI() + "!/nested.jar"); .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); assertThat(conn.getPermission()).isInstanceOf(FilePermission.class);
FilePermission permission = (FilePermission) conn.getPermission(); FilePermission permission = (FilePermission) conn.getPermission();
assertThat(permission.getActions()).isEqualTo("read"); assertThat(permission.getActions()).isEqualTo("read");
......
...@@ -30,6 +30,7 @@ import org.springframework.boot.ApplicationPid; ...@@ -30,6 +30,7 @@ import org.springframework.boot.ApplicationPid;
import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.SpringApplicationEvent; import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
...@@ -49,7 +50,8 @@ import org.springframework.util.Assert; ...@@ -49,7 +50,8 @@ import org.springframework.util.Assert;
* <p> * <p>
* Note: access to the Spring {@link Environment} is only possible when the * Note: access to the Spring {@link Environment} is only possible when the
* {@link #setTriggerEventType(Class) triggerEventType} is set to * {@link #setTriggerEventType(Class) triggerEventType} is set to
* {@link ApplicationEnvironmentPreparedEvent} or {@link ApplicationPreparedEvent}. * {@link ApplicationEnvironmentPreparedEvent}, {@link ApplicationReadyEvent}, or
* {@link ApplicationPreparedEvent}.
* *
* @author Jakub Kubrynski * @author Jakub Kubrynski
* @author Dave Syer * @author Dave Syer
...@@ -231,6 +233,10 @@ public class ApplicationPidFileWriter ...@@ -231,6 +233,10 @@ public class ApplicationPidFileWriter
return ((ApplicationPreparedEvent) event).getApplicationContext() return ((ApplicationPreparedEvent) event).getApplicationContext()
.getEnvironment(); .getEnvironment();
} }
if (event instanceof ApplicationReadyEvent) {
return ((ApplicationReadyEvent) event).getApplicationContext()
.getEnvironment();
}
return null; return null;
} }
......
...@@ -29,6 +29,7 @@ import org.junit.rules.TemporaryFolder; ...@@ -29,6 +29,7 @@ import org.junit.rules.TemporaryFolder;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.boot.context.event.SpringApplicationEvent; import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
...@@ -99,7 +100,7 @@ public class ApplicationPidFileWriterTests { ...@@ -99,7 +100,7 @@ public class ApplicationPidFileWriterTests {
} }
@Test @Test
public void differentEventTypes() throws Exception { public void tryEnvironmentPreparedEvent() throws Exception {
File file = this.temporaryFolder.newFile(); File file = this.temporaryFolder.newFile();
SpringApplicationEvent event = createEnvironmentPreparedEvent("spring.pid.file", SpringApplicationEvent event = createEnvironmentPreparedEvent("spring.pid.file",
file.getAbsolutePath()); file.getAbsolutePath());
...@@ -111,6 +112,19 @@ public class ApplicationPidFileWriterTests { ...@@ -111,6 +112,19 @@ public class ApplicationPidFileWriterTests {
assertThat(FileCopyUtils.copyToString(new FileReader(file))).isNotEmpty(); assertThat(FileCopyUtils.copyToString(new FileReader(file))).isNotEmpty();
} }
@Test
public void tryReadyEvent() throws Exception {
File file = this.temporaryFolder.newFile();
SpringApplicationEvent event = createReadyEvent("spring.pid.file",
file.getAbsolutePath());
ApplicationPidFileWriter listener = new ApplicationPidFileWriter();
listener.onApplicationEvent(event);
assertThat(FileCopyUtils.copyToString(new FileReader(file))).isEmpty();
listener.setTriggerEventType(ApplicationReadyEvent.class);
listener.onApplicationEvent(event);
assertThat(FileCopyUtils.copyToString(new FileReader(file))).isNotEmpty();
}
@Test @Test
public void withNoEnvironment() throws Exception { public void withNoEnvironment() throws Exception {
File file = this.temporaryFolder.newFile(); File file = this.temporaryFolder.newFile();
...@@ -170,6 +184,15 @@ public class ApplicationPidFileWriterTests { ...@@ -170,6 +184,15 @@ public class ApplicationPidFileWriterTests {
context); context);
} }
private SpringApplicationEvent createReadyEvent(String propName, String propValue) {
ConfigurableEnvironment environment = createEnvironment(propName, propValue);
ConfigurableApplicationContext context = mock(
ConfigurableApplicationContext.class);
given(context.getEnvironment()).willReturn(environment);
return new ApplicationReadyEvent(new SpringApplication(), new String[] {},
context);
}
private ConfigurableEnvironment createEnvironment(String propName, String propValue) { private ConfigurableEnvironment createEnvironment(String propName, String propValue) {
MockPropertySource propertySource = mockPropertySource(propName, propValue); MockPropertySource propertySource = mockPropertySource(propName, propValue);
ConfigurableEnvironment environment = new StandardEnvironment(); ConfigurableEnvironment environment = new StandardEnvironment();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment