Skip to content

Commit 3dab52d

Browse files
committed
Merge pull request #29755 from hpoettker
* gh-29755: Reinstate support for H2 Console Closes gh-29755
2 parents 7fb065d + 7d83dfc commit 3dab52d

File tree

10 files changed

+635
-2
lines changed

10 files changed

+635
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.h2;
18+
19+
import java.sql.Connection;
20+
import java.util.List;
21+
import java.util.Objects;
22+
import java.util.stream.Collectors;
23+
24+
import javax.sql.DataSource;
25+
26+
import org.apache.commons.logging.Log;
27+
import org.apache.commons.logging.LogFactory;
28+
import org.h2.server.web.JakartaWebServlet;
29+
30+
import org.springframework.beans.factory.ObjectProvider;
31+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
32+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
33+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
34+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
35+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
36+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
37+
import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties.Settings;
38+
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
39+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
40+
import org.springframework.boot.web.servlet.ServletRegistrationBean;
41+
import org.springframework.context.annotation.Bean;
42+
import org.springframework.context.annotation.Configuration;
43+
44+
/**
45+
* {@link EnableAutoConfiguration Auto-configuration} for H2's web console.
46+
*
47+
* @author Andy Wilkinson
48+
* @author Marten Deinum
49+
* @author Stephane Nicoll
50+
* @since 1.3.0
51+
*/
52+
@Configuration(proxyBeanMethods = false)
53+
@ConditionalOnWebApplication(type = Type.SERVLET)
54+
@ConditionalOnClass(JakartaWebServlet.class)
55+
@ConditionalOnProperty(prefix = "spring.h2.console", name = "enabled", havingValue = "true")
56+
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
57+
@EnableConfigurationProperties(H2ConsoleProperties.class)
58+
public class H2ConsoleAutoConfiguration {
59+
60+
private static final Log logger = LogFactory.getLog(H2ConsoleAutoConfiguration.class);
61+
62+
@Bean
63+
public ServletRegistrationBean<JakartaWebServlet> h2Console(H2ConsoleProperties properties,
64+
ObjectProvider<DataSource> dataSource) {
65+
String path = properties.getPath();
66+
String urlMapping = path + (path.endsWith("/") ? "*" : "/*");
67+
ServletRegistrationBean<JakartaWebServlet> registration = new ServletRegistrationBean<>(new JakartaWebServlet(),
68+
urlMapping);
69+
configureH2ConsoleSettings(registration, properties.getSettings());
70+
if (logger.isInfoEnabled()) {
71+
logDataSources(dataSource, path);
72+
}
73+
return registration;
74+
}
75+
76+
private void logDataSources(ObjectProvider<DataSource> dataSource, String path) {
77+
List<String> urls = dataSource.orderedStream().map((available) -> {
78+
try (Connection connection = available.getConnection()) {
79+
return "'" + connection.getMetaData().getURL() + "'";
80+
}
81+
catch (Exception ex) {
82+
return null;
83+
}
84+
}).filter(Objects::nonNull).collect(Collectors.toList());
85+
if (!urls.isEmpty()) {
86+
StringBuilder sb = new StringBuilder("H2 console available at '").append(path).append("'. ");
87+
String tmp = (urls.size() > 1) ? "Databases" : "Database";
88+
sb.append(tmp).append(" available at ");
89+
sb.append(String.join(", ", urls));
90+
logger.info(sb.toString());
91+
}
92+
}
93+
94+
private void configureH2ConsoleSettings(ServletRegistrationBean<JakartaWebServlet> registration,
95+
Settings settings) {
96+
if (settings.isTrace()) {
97+
registration.addInitParameter("trace", "");
98+
}
99+
if (settings.isWebAllowOthers()) {
100+
registration.addInitParameter("webAllowOthers", "");
101+
}
102+
if (settings.getWebAdminPassword() != null) {
103+
registration.addInitParameter("webAdminPassword", settings.getWebAdminPassword());
104+
}
105+
}
106+
107+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.h2;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
import org.springframework.util.Assert;
21+
22+
/**
23+
* Configuration properties for H2's console.
24+
*
25+
* @author Andy Wilkinson
26+
* @author Marten Deinum
27+
* @author Stephane Nicoll
28+
* @since 1.3.0
29+
*/
30+
@ConfigurationProperties(prefix = "spring.h2.console")
31+
public class H2ConsoleProperties {
32+
33+
/**
34+
* Path at which the console is available.
35+
*/
36+
private String path = "/h2-console";
37+
38+
/**
39+
* Whether to enable the console.
40+
*/
41+
private boolean enabled = false;
42+
43+
private final Settings settings = new Settings();
44+
45+
public String getPath() {
46+
return this.path;
47+
}
48+
49+
public void setPath(String path) {
50+
Assert.notNull(path, "Path must not be null");
51+
Assert.isTrue(path.length() > 1, "Path must have length greater than 1");
52+
Assert.isTrue(path.startsWith("/"), "Path must start with '/'");
53+
this.path = path;
54+
}
55+
56+
public boolean getEnabled() {
57+
return this.enabled;
58+
}
59+
60+
public void setEnabled(boolean enabled) {
61+
this.enabled = enabled;
62+
}
63+
64+
public Settings getSettings() {
65+
return this.settings;
66+
}
67+
68+
public static class Settings {
69+
70+
/**
71+
* Whether to enable trace output.
72+
*/
73+
private boolean trace = false;
74+
75+
/**
76+
* Whether to enable remote access.
77+
*/
78+
private boolean webAllowOthers = false;
79+
80+
/**
81+
* Password to access preferences and tools of H2 Console.
82+
*/
83+
private String webAdminPassword;
84+
85+
public boolean isTrace() {
86+
return this.trace;
87+
}
88+
89+
public void setTrace(boolean trace) {
90+
this.trace = trace;
91+
}
92+
93+
public boolean isWebAllowOthers() {
94+
return this.webAllowOthers;
95+
}
96+
97+
public void setWebAllowOthers(boolean webAllowOthers) {
98+
this.webAllowOthers = webAllowOthers;
99+
}
100+
101+
public String getWebAdminPassword() {
102+
return this.webAdminPassword;
103+
}
104+
105+
public void setWebAdminPassword(String webAdminPassword) {
106+
this.webAdminPassword = webAdminPassword;
107+
}
108+
109+
}
110+
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Auto-configuration for H2's Console.
19+
*/
20+
package org.springframework.boot.autoconfigure.h2;

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/PathRequest.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,8 +16,17 @@
1616

1717
package org.springframework.boot.autoconfigure.security.servlet;
1818

19+
import java.util.function.Supplier;
20+
21+
import jakarta.servlet.http.HttpServletRequest;
22+
23+
import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties;
1924
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
25+
import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
26+
import org.springframework.boot.web.context.WebServerApplicationContext;
27+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
2028
import org.springframework.security.web.util.matcher.RequestMatcher;
29+
import org.springframework.web.context.WebApplicationContext;
2130

2231
/**
2332
* Factory that can be used to create a {@link RequestMatcher} for commonly used paths.
@@ -40,4 +49,43 @@ public static StaticResourceRequest toStaticResources() {
4049
return StaticResourceRequest.INSTANCE;
4150
}
4251

52+
/**
53+
* Returns a matcher that includes the H2 console location. For example:
54+
* <pre class="code">
55+
* PathRequest.toH2Console()
56+
* </pre>
57+
* @return the configured {@link RequestMatcher}
58+
*/
59+
public static H2ConsoleRequestMatcher toH2Console() {
60+
return new H2ConsoleRequestMatcher();
61+
}
62+
63+
/**
64+
* The request matcher used to match against h2 console path.
65+
*/
66+
public static final class H2ConsoleRequestMatcher extends ApplicationContextRequestMatcher<H2ConsoleProperties> {
67+
68+
private volatile RequestMatcher delegate;
69+
70+
private H2ConsoleRequestMatcher() {
71+
super(H2ConsoleProperties.class);
72+
}
73+
74+
@Override
75+
protected boolean ignoreApplicationContext(WebApplicationContext applicationContext) {
76+
return WebServerApplicationContext.hasServerNamespace(applicationContext, "management");
77+
}
78+
79+
@Override
80+
protected void initialized(Supplier<H2ConsoleProperties> h2ConsoleProperties) {
81+
this.delegate = new AntPathRequestMatcher(h2ConsoleProperties.get().getPath() + "/**");
82+
}
83+
84+
@Override
85+
protected boolean matches(HttpServletRequest request, Supplier<H2ConsoleProperties> context) {
86+
return this.delegate.matches(request);
87+
}
88+
89+
}
90+
4391
}

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
7070
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
7171
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
7272
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
73+
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
7374
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
7475
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
7576
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\

0 commit comments

Comments
 (0)