diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java index ca7a364e1b..c0cd49d08d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -40,7 +40,8 @@ public class LiquibaseServiceLocatorApplicationListener @Override public void onApplicationEvent(ApplicationStartingEvent event) { - if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) { + if (ClassUtils.isPresent("liquibase.servicelocator.CustomResolverServiceLocator", + event.getSpringApplication().getClassLoader())) { new LiquibasePresent().replaceServiceLocator(); } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java index 54a1aae6ca..b5f2db070b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -17,7 +17,13 @@ package org.springframework.boot.liquibase; import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.List; +import liquibase.servicelocator.CustomResolverServiceLocator; +import liquibase.servicelocator.DefaultPackageScanClassResolver; import liquibase.servicelocator.ServiceLocator; import org.junit.After; import org.junit.Test; @@ -26,6 +32,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.DefaultResourceLoader; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -34,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link LiquibaseServiceLocatorApplicationListener}. * * @author Phillip Webb + * @author Stephane Nicoll */ public class LiquibaseServiceLocatorApplicationListenerTests { @@ -47,15 +55,33 @@ public class LiquibaseServiceLocatorApplicationListenerTests { } @Test - public void replacesServiceLocator() throws Exception { + public void replacesServiceLocator() throws IllegalAccessException { SpringApplication application = new SpringApplication(Conf.class); application.setWebApplicationType(WebApplicationType.NONE); this.context = application.run(); + Object resolver = getServiceLocator(); + assertThat(resolver).isInstanceOf(SpringPackageScanClassResolver.class); + } + + @Test + public void replaceServiceLocatorBacksOffIfNotPresent() + throws IllegalAccessException { + SpringApplication application = new SpringApplication(Conf.class); + application.setWebApplicationType(WebApplicationType.NONE); + DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); + resourceLoader.setClassLoader(new ClassHidingClassLoader( + CustomResolverServiceLocator.class)); + application.setResourceLoader(resourceLoader); + this.context = application.run(); + Object resolver = getServiceLocator(); + assertThat(resolver).isInstanceOf(DefaultPackageScanClassResolver.class); + } + + private Object getServiceLocator() throws IllegalAccessException { ServiceLocator instance = ServiceLocator.getInstance(); Field field = ReflectionUtils.findField(ServiceLocator.class, "classResolver"); field.setAccessible(true); - Object resolver = field.get(instance); - assertThat(resolver).isInstanceOf(SpringPackageScanClassResolver.class); + return field.get(instance); } @Configuration @@ -63,4 +89,32 @@ public class LiquibaseServiceLocatorApplicationListenerTests { } + private final class ClassHidingClassLoader extends URLClassLoader { + + private final List> hiddenClasses; + + private ClassHidingClassLoader(Class... hiddenClasses) { + super(new URL[0], LiquibaseServiceLocatorApplicationListenerTests.class.getClassLoader()); + this.hiddenClasses = Arrays.asList(hiddenClasses); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (isHidden(name)) { + throw new ClassNotFoundException(); + } + return super.loadClass(name); + } + + private boolean isHidden(String name) { + for (Class hiddenClass : this.hiddenClasses) { + if (hiddenClass.getName().equals(name)) { + return true; + } + } + return false; + } + + } + }