Make QuarkusLiquibaseConnectionProvider extending DefaultLiquibaseConnectionProvider to allow indexCreationThreshold working

Closes #32860

Signed-off-by: vramik <vramik@redhat.com>
This commit is contained in:
vramik 2024-09-18 12:22:03 +02:00 committed by Alexander Schwartz
parent 493252befd
commit 87fbe23270
16 changed files with 111 additions and 168 deletions

View file

@ -27,7 +27,7 @@ import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.logging.LoggingSetupBuildItem;
import jakarta.enterprise.context.ApplicationScoped;
import org.keycloak.quarkus.runtime.KeycloakRecorder;
import org.keycloak.quarkus.runtime.storage.legacy.infinispan.CacheManagerFactory;
import org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory;
public class CacheBuildSteps {

View file

@ -162,7 +162,7 @@ import static org.keycloak.quarkus.runtime.configuration.Configuration.getProper
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_QUARKUS;
import static org.keycloak.quarkus.runtime.configuration.QuarkusPropertiesConfigSource.QUARKUS_PROPERTY_ENABLED;
import static org.keycloak.quarkus.runtime.storage.legacy.database.QuarkusJpaConnectionProviderFactory.QUERY_PROPERTY_PREFIX;
import static org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory.QUERY_PROPERTY_PREFIX;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.AUTHENTICATORS;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.MAPPERS;
import static org.keycloak.representations.provider.ScriptProviderDescriptor.POLICIES;

View file

@ -44,7 +44,7 @@ import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider;
import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory;
import org.keycloak.quarkus.runtime.storage.database.liquibase.FastServiceLocator;
import org.keycloak.quarkus.runtime.storage.legacy.infinispan.CacheManagerFactory;
import org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory;
import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.theme.ClasspathThemeProviderFactory;
import org.keycloak.truststore.TruststoreBuilder;

View file

@ -15,10 +15,10 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.database;
package org.keycloak.quarkus.runtime.storage.database.jpa;
import static org.keycloak.connections.jpa.util.JpaUtils.configureNamedQuery;
import static org.keycloak.quarkus.runtime.storage.legacy.liquibase.QuarkusJpaUpdaterProvider.VERIFY_AND_RUN_MASTER_CHANGELOG;
import static org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusJpaUpdaterProvider.VERIFY_AND_RUN_MASTER_CHANGELOG;
import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
import java.io.File;
@ -54,7 +54,6 @@ import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.provider.ProviderConfigurationBuilder;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.storage.database.jpa.AbstractJpaConnectionProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.liquibase;
package org.keycloak.quarkus.runtime.storage.database.liquibase;
import java.io.File;
import java.io.FileWriter;

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.liquibase;
package org.keycloak.quarkus.runtime.storage.database.liquibase;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;

View file

@ -0,0 +1,79 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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.keycloak.quarkus.runtime.storage.database.liquibase;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import liquibase.Scope;
import liquibase.parser.ChangeLogParser;
import liquibase.parser.ChangeLogParserFactory;
import liquibase.parser.core.xml.XMLChangeLogSAXParser;
import liquibase.ui.LoggerUIService;
import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.updater.liquibase.conn.DefaultLiquibaseConnectionProvider;
public class QuarkusLiquibaseConnectionProvider extends DefaultLiquibaseConnectionProvider {
private static final Logger logger = Logger.getLogger(QuarkusLiquibaseConnectionProvider.class);
@Override
protected void baseLiquibaseInitialization() {
// initialize Liquibase using a custom scope
final Map<String, Object> scopeValues = new HashMap<>();
scopeValues.put(Scope.Attr.ui.name(), new LoggerUIService());
try {
Scope.enter(scopeValues);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize Liquibase: " + e.getMessage(), e);
}
// disables XML validation
for (ChangeLogParser parser : ChangeLogParserFactory.getInstance().getParsers()) {
if (parser instanceof XMLChangeLogSAXParser) {
Method getSaxParserFactory = null;
try {
getSaxParserFactory = XMLChangeLogSAXParser.class.getDeclaredMethod("getSaxParserFactory");
getSaxParserFactory.setAccessible(true);
SAXParserFactory saxParserFactory = (SAXParserFactory) getSaxParserFactory.invoke(parser);
saxParserFactory.setValidating(false);
saxParserFactory.setSchema(null);
} catch (Exception e) {
logger.warnf("Failed to disable liquibase XML validations");
} finally {
if (getSaxParserFactory != null) {
getSaxParserFactory.setAccessible(false);
}
}
}
}
}
@Override
public String getId() {
return "quarkus";
}
@Override
public int order() {
return 100;
}
}

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.infinispan;
package org.keycloak.quarkus.runtime.storage.infinispan;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.infinispan;
package org.keycloak.quarkus.runtime.storage.infinispan;
import io.quarkus.arc.Arc;
import org.keycloak.Config;

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.legacy.infinispan;
package org.keycloak.quarkus.runtime.storage.infinispan;
import org.infinispan.manager.EmbeddedCacheManager;
import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory;

View file

@ -1,152 +0,0 @@
/*
* Copyright 2021 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* 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.keycloak.quarkus.runtime.storage.legacy.liquibase;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import liquibase.Scope;
import liquibase.ui.LoggerUIService;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.liquibase.conn.KeycloakLiquibase;
import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProvider;
import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.parser.ChangeLogParser;
import liquibase.parser.ChangeLogParserFactory;
import liquibase.parser.core.xml.XMLChangeLogSAXParser;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor;
public class QuarkusLiquibaseConnectionProvider implements LiquibaseConnectionProviderFactory, LiquibaseConnectionProvider {
private static final Logger logger = Logger.getLogger(QuarkusLiquibaseConnectionProvider.class);
private volatile boolean initialized = false;
private ClassLoaderResourceAccessor resourceAccessor;
@Override
public LiquibaseConnectionProvider create(KeycloakSession session) {
if (!initialized) {
synchronized (this) {
if (!initialized) {
baseLiquibaseInitialization(session);
initialized = true;
}
}
}
return this;
}
protected void baseLiquibaseInitialization(KeycloakSession session) {
resourceAccessor = new ClassLoaderResourceAccessor(getClass().getClassLoader());
// initialize Liquibase using a custom scope
final Map<String, Object> scopeValues = new HashMap<>();
scopeValues.put(Scope.Attr.ui.name(), new LoggerUIService());
try {
Scope scope = Scope.getCurrentScope();
scope.enter(scopeValues);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize Liquibase: " + e.getMessage(), e);
}
// disables XML validation
for (ChangeLogParser parser : ChangeLogParserFactory.getInstance().getParsers()) {
if (parser instanceof XMLChangeLogSAXParser) {
Method getSaxParserFactory = null;
try {
getSaxParserFactory = XMLChangeLogSAXParser.class.getDeclaredMethod("getSaxParserFactory");
getSaxParserFactory.setAccessible(true);
SAXParserFactory saxParserFactory = (SAXParserFactory) getSaxParserFactory.invoke(parser);
saxParserFactory.setValidating(false);
saxParserFactory.setSchema(null);
} catch (Exception e) {
logger.warnf("Failed to disable liquibase XML validations");
} finally {
if (getSaxParserFactory != null) {
getSaxParserFactory.setAccessible(false);
}
}
}
}
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "quarkus";
}
@Override
public KeycloakLiquibase getLiquibase(Connection connection, String defaultSchema) throws LiquibaseException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
if (defaultSchema != null) {
database.setDefaultSchemaName(defaultSchema);
}
String changelog = QuarkusJpaUpdaterProvider.CHANGELOG;
logger.debugf("Using changelog file %s and changelogTableName %s", changelog, database.getDatabaseChangeLogTableName());
return new KeycloakLiquibase(changelog, resourceAccessor, database);
}
@Override
public KeycloakLiquibase getLiquibaseForCustomUpdate(Connection connection, String defaultSchema, String changelogLocation, ClassLoader classloader, String changelogTableName) throws LiquibaseException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
if (defaultSchema != null) {
database.setDefaultSchemaName(defaultSchema);
}
ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(classloader);
database.setDatabaseChangeLogTableName(changelogTableName);
logger.debugf("Using changelog file %s and changelogTableName %s", changelogLocation, database.getDatabaseChangeLogTableName());
return new KeycloakLiquibase(changelogLocation, resourceAccessor, database);
}
@Override
public int order() {
return 100;
}
}

View file

@ -1 +1,18 @@
org.keycloak.quarkus.runtime.storage.legacy.infinispan.QuarkusCacheManagerProvider
#
# Copyright 2021 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# 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.
#
org.keycloak.quarkus.runtime.storage.infinispan.QuarkusCacheManagerProvider

View file

@ -17,4 +17,4 @@
# */
#
org.keycloak.quarkus.runtime.storage.legacy.infinispan.QuarkusInfinispanConnectionFactory
org.keycloak.quarkus.runtime.storage.infinispan.QuarkusInfinispanConnectionFactory

View file

@ -15,4 +15,4 @@
# limitations under the License.
#
org.keycloak.quarkus.runtime.storage.legacy.database.QuarkusJpaConnectionProviderFactory
org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory

View file

@ -15,4 +15,4 @@
# limitations under the License.
#
org.keycloak.quarkus.runtime.storage.legacy.liquibase.QuarkusJpaUpdaterProviderFactory
org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusJpaUpdaterProviderFactory

View file

@ -15,4 +15,4 @@
# limitations under the License.
#
org.keycloak.quarkus.runtime.storage.legacy.liquibase.QuarkusLiquibaseConnectionProvider
org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusLiquibaseConnectionProvider