001// Generated by delombok at Fri Mar 22 16:21:46 GMT 2024 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020package org.apache.causeway.testing.h2console.ui.webmodule; 021 022import javax.inject.Inject; 023import javax.inject.Named; 024import javax.servlet.ServletContext; 025import javax.servlet.ServletContextListener; 026import javax.servlet.ServletException; 027import org.h2.server.web.ConnectionInfo; 028import org.h2.server.web.WebServlet; 029import org.springframework.beans.factory.annotation.Qualifier; 030import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; 031import org.springframework.stereotype.Service; 032import org.apache.causeway.applib.annotation.PriorityPrecedence; 033import org.apache.causeway.applib.services.inject.ServiceInjector; 034import org.apache.causeway.applib.value.LocalResourcePath; 035import org.apache.causeway.commons.collections.Can; 036import org.apache.causeway.commons.internal.base._Strings; 037import org.apache.causeway.core.config.CausewayConfiguration; 038import org.apache.causeway.core.config.datasources.DataSourceIntrospectionService; 039import org.apache.causeway.core.config.datasources.DataSourceIntrospectionService.DataSourceInfo; 040import org.apache.causeway.core.config.environment.CausewaySystemEnvironment; 041import org.apache.causeway.core.security.authentication.standard.RandomCodeGenerator; 042import org.apache.causeway.core.webapp.modules.WebModuleAbstract; 043import org.apache.causeway.core.webapp.modules.WebModuleContext; 044 045/** 046 * @since 2.0 {@index} 047 */ 048@Service 049@Named("causeway.test.WebModuleH2Console") 050@javax.annotation.Priority(PriorityPrecedence.MIDPOINT) 051@Qualifier("H2Console") 052public class WebModuleH2Console extends WebModuleAbstract { 053 @java.lang.SuppressWarnings("all") 054 private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(WebModuleH2Console.class); 055 private static final String SERVLET_NAME = "H2Console"; 056 private static final String CONSOLE_PATH = "/db"; 057 private final LocalResourcePath localResourcePathIfEnabled; 058 private final CausewaySystemEnvironment causewaySystemEnvironment; 059 private final boolean applicable; 060 061 @Inject 062 public WebModuleH2Console(final DataSourceIntrospectionService datasourceIntrospector, final CausewaySystemEnvironment causewaySystemEnvironment, final ServiceInjector serviceInjector) { 063 super(serviceInjector); 064 this.causewaySystemEnvironment = causewaySystemEnvironment; 065 this.applicable = isPrototyping() && isH2MemConnectionUsed(datasourceIntrospector); 066 this.localResourcePathIfEnabled = applicable ? new LocalResourcePath(CONSOLE_PATH) : null; 067 } 068 069 private final String name = "H2Console"; 070 071 @Override 072 public Can<ServletContextListener> init(final ServletContext ctx) throws ServletException { 073 registerServlet(ctx, SERVLET_NAME, H2WebServlet.class).ifPresent(servletReg -> { 074 servletReg.addMapping(CONSOLE_PATH + "/*"); 075 }); 076 //[CAUSEWAY-3128] presence of "webAllowOthers" is a potential security risk 077 // setting this later based on configuration below ... 078 //servletReg.setInitParameter("webAllowOthers", "true"); 079 return Can.empty(); // registers no listeners 080 } 081 082 @Override 083 public boolean isApplicable(final WebModuleContext ctx) { 084 return applicable; 085 } 086 087 // -- WRAPPER AROUND H2'S SERVLET 088 public static class H2WebServlet extends WebServlet { 089 private static final long serialVersionUID = 1L; 090 private static String jdbcUrl; 091 @Inject 092 private CausewayConfiguration causewayConfiguration; 093 @Inject 094 private RandomCodeGenerator randomCodeGenerator; 095 096 @Override 097 public void init() { 098 super.init(); 099 if (_Strings.isEmpty(jdbcUrl)) { 100 return; 101 } 102 final org.springframework.boot.autoconfigure.jdbc.DataSourceProperties dataSourceProperties = new DataSourceProperties(); 103 dataSourceProperties.setUsername("sa"); 104 dataSourceProperties.setUrl(jdbcUrl); 105 final org.h2.server.web.ConnectionInfo connectionInfo = new ConnectionInfo(String.format("Generic Spring Datasource|%s|%s|%s", dataSourceProperties.determineDriverClassName(), dataSourceProperties.determineUrl(), dataSourceProperties.determineUsername())); 106 final org.apache.causeway.testing.h2console.ui.webmodule.WebModuleH2Console.H2WebServlet webServlet = this; 107 H2WebServerWrapper.withH2WebServerWrapperDo(webServlet, h2WebServerWrapper -> { 108 h2WebServerWrapper.setConnectionInfo(connectionInfo); 109 h2WebServerWrapper.setAllowOthers(isWebAllowRemoteAccess()); 110 if (isGenerateRandomWebAdminPassword()) { 111 final java.lang.String webAdminPass = randomCodeGenerator.generateRandomCode(); 112 log.info("webAdminPass: {}", webAdminPass); 113 h2WebServerWrapper.setAdminPassword(webAdminPass); 114 } 115 }); 116 } 117 118 public static void configure(final String jdbcUrl) { 119 H2WebServlet.jdbcUrl = jdbcUrl; 120 } 121 122 private boolean isWebAllowRemoteAccess() { 123 return causewayConfiguration.getPrototyping().getH2Console().isWebAllowRemoteAccess(); 124 } 125 126 private boolean isGenerateRandomWebAdminPassword() { 127 return causewayConfiguration.getPrototyping().getH2Console().isGenerateRandomWebAdminPassword(); 128 } 129 } 130 131 // -- HELPER 132 private boolean isPrototyping() { 133 return causewaySystemEnvironment.getDeploymentType().isPrototyping(); 134 } 135 136 private boolean isH2MemConnectionUsed(final DataSourceIntrospectionService datasourceIntrospector) { 137 return datasourceIntrospector.getDataSourceInfos().stream().map(DataSourceInfo::getJdbcUrl).anyMatch(jdbcUrl -> { 138 if (jdbcUrl.contains(":h2:mem:")) { 139 log.info("found h2 in-memory data-source: {}", jdbcUrl); 140 H2WebServlet.configure(jdbcUrl); 141 return true; 142 } 143 return false; 144 }); 145 } 146 147 @java.lang.SuppressWarnings("all") 148 public LocalResourcePath getLocalResourcePathIfEnabled() { 149 return this.localResourcePathIfEnabled; 150 } 151 152 @java.lang.SuppressWarnings("all") 153 public String getName() { 154 return this.name; 155 } 156}