|
|
|
|
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
|
|
|
|
/* |
|
|
|
|
* Copyright 2012-2022 the original author or authors. |
|
|
|
|
* Copyright 2012-2024 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. |
|
|
|
|
@ -46,6 +46,7 @@ import org.springframework.core.log.LogMessage;
@@ -46,6 +46,7 @@ import org.springframework.core.log.LogMessage;
|
|
|
|
|
* @author Andy Wilkinson |
|
|
|
|
* @author Marten Deinum |
|
|
|
|
* @author Stephane Nicoll |
|
|
|
|
* @author Phillip Webb |
|
|
|
|
* @since 1.3.0 |
|
|
|
|
*/ |
|
|
|
|
@AutoConfiguration(after = DataSourceAutoConfiguration.class) |
|
|
|
|
@ -57,46 +58,25 @@ public class H2ConsoleAutoConfiguration {
@@ -57,46 +58,25 @@ public class H2ConsoleAutoConfiguration {
|
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(H2ConsoleAutoConfiguration.class); |
|
|
|
|
|
|
|
|
|
private final H2ConsoleProperties properties; |
|
|
|
|
|
|
|
|
|
H2ConsoleAutoConfiguration(H2ConsoleProperties properties) { |
|
|
|
|
this.properties = properties; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
public ServletRegistrationBean<JakartaWebServlet> h2Console(H2ConsoleProperties properties, |
|
|
|
|
ObjectProvider<DataSource> dataSource) { |
|
|
|
|
String path = properties.getPath(); |
|
|
|
|
public ServletRegistrationBean<JakartaWebServlet> h2Console() { |
|
|
|
|
String path = this.properties.getPath(); |
|
|
|
|
String urlMapping = path + (path.endsWith("/") ? "*" : "/*"); |
|
|
|
|
ServletRegistrationBean<JakartaWebServlet> registration = new ServletRegistrationBean<>(new JakartaWebServlet(), |
|
|
|
|
urlMapping); |
|
|
|
|
configureH2ConsoleSettings(registration, properties.getSettings()); |
|
|
|
|
if (logger.isInfoEnabled()) { |
|
|
|
|
withThreadContextClassLoader(getClass().getClassLoader(), () -> logDataSources(dataSource, path)); |
|
|
|
|
} |
|
|
|
|
configureH2ConsoleSettings(registration, this.properties.getSettings()); |
|
|
|
|
return registration; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void withThreadContextClassLoader(ClassLoader classLoader, Runnable action) { |
|
|
|
|
ClassLoader previous = Thread.currentThread().getContextClassLoader(); |
|
|
|
|
try { |
|
|
|
|
Thread.currentThread().setContextClassLoader(classLoader); |
|
|
|
|
action.run(); |
|
|
|
|
} |
|
|
|
|
finally { |
|
|
|
|
Thread.currentThread().setContextClassLoader(previous); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void logDataSources(ObjectProvider<DataSource> dataSource, String path) { |
|
|
|
|
List<String> urls = dataSource.orderedStream().map(this::getConnectionUrl).filter(Objects::nonNull).toList(); |
|
|
|
|
if (!urls.isEmpty()) { |
|
|
|
|
logger.info(LogMessage.format("H2 console available at '%s'. %s available at %s", path, |
|
|
|
|
(urls.size() > 1) ? "Databases" : "Database", String.join(", ", urls))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String getConnectionUrl(DataSource dataSource) { |
|
|
|
|
try (Connection connection = dataSource.getConnection()) { |
|
|
|
|
return "'" + connection.getMetaData().getURL() + "'"; |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
@Bean |
|
|
|
|
H2ConsoleLogger h2ConsoleLogger(ObjectProvider<DataSource> dataSource) { |
|
|
|
|
return new H2ConsoleLogger(dataSource, this.properties.getPath()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void configureH2ConsoleSettings(ServletRegistrationBean<JakartaWebServlet> registration, |
|
|
|
|
@ -112,4 +92,46 @@ public class H2ConsoleAutoConfiguration {
@@ -112,4 +92,46 @@ public class H2ConsoleAutoConfiguration {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static class H2ConsoleLogger { |
|
|
|
|
|
|
|
|
|
H2ConsoleLogger(ObjectProvider<DataSource> dataSources, String path) { |
|
|
|
|
if (logger.isInfoEnabled()) { |
|
|
|
|
ClassLoader classLoader = getClass().getClassLoader(); |
|
|
|
|
withThreadContextClassLoader(classLoader, () -> log(getConnectionUrls(dataSources), path)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void withThreadContextClassLoader(ClassLoader classLoader, Runnable action) { |
|
|
|
|
ClassLoader previous = Thread.currentThread().getContextClassLoader(); |
|
|
|
|
try { |
|
|
|
|
Thread.currentThread().setContextClassLoader(classLoader); |
|
|
|
|
action.run(); |
|
|
|
|
} |
|
|
|
|
finally { |
|
|
|
|
Thread.currentThread().setContextClassLoader(previous); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private List<String> getConnectionUrls(ObjectProvider<DataSource> dataSources) { |
|
|
|
|
return dataSources.orderedStream().map(this::getConnectionUrl).filter(Objects::nonNull).toList(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String getConnectionUrl(DataSource dataSource) { |
|
|
|
|
try (Connection connection = dataSource.getConnection()) { |
|
|
|
|
return "'" + connection.getMetaData().getURL() + "'"; |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void log(List<String> urls, String path) { |
|
|
|
|
if (!urls.isEmpty()) { |
|
|
|
|
logger.info(LogMessage.format("H2 console available at '%s'. %s available at %s", path, |
|
|
|
|
(urls.size() > 1) ? "Databases" : "Database", String.join(", ", urls))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|