001package com.nimbusds.infinispan.persistence.sql.config; 002 003 004import java.util.Properties; 005 006import net.jcip.annotations.Immutable; 007import org.apache.commons.lang3.StringUtils; 008import org.infinispan.commons.configuration.BuiltBy; 009import org.infinispan.commons.configuration.ConfigurationFor; 010import org.infinispan.commons.configuration.attributes.Attribute; 011import org.infinispan.commons.configuration.attributes.AttributeDefinition; 012import org.infinispan.commons.configuration.attributes.AttributeSet; 013import org.infinispan.commons.util.StringPropertyReplacer; 014import org.infinispan.configuration.cache.AbstractStoreConfiguration; 015import org.infinispan.configuration.cache.AsyncStoreConfiguration; 016import org.jooq.SQLDialect; 017 018import com.nimbusds.common.config.LoggableConfiguration; 019import com.nimbusds.infinispan.persistence.sql.Loggers; 020import com.nimbusds.infinispan.persistence.sql.SQLRecordTransformer; 021import com.nimbusds.infinispan.persistence.sql.SQLStore; 022 023 024/** 025 * SQL store configuration. 026 */ 027@Immutable 028@BuiltBy(SQLStoreConfigurationBuilder.class) 029@ConfigurationFor(SQLStore.class) 030public class SQLStoreConfiguration extends AbstractStoreConfiguration implements LoggableConfiguration { 031 032 033 /** 034 * The attribute definition for the record transformer class. 035 */ 036 static final AttributeDefinition<Class> RECORD_TRANSFORMER = AttributeDefinition.builder("recordTransformer", null, Class.class).build(); 037 038 039 /** 040 * The attribute definition for the query executor class. 041 */ 042 static final AttributeDefinition<Class> QUERY_EXECUTOR = AttributeDefinition.builder("queryExecutor", null, Class.class).build(); 043 044 045 /** 046 * The attribute definition for the SQL dialect. 047 */ 048 static final AttributeDefinition<SQLDialect> SQL_DIALECT = AttributeDefinition.builder("sqlDialect", SQLDialect.DEFAULT).build(); 049 050 051 /** 052 * The attribute definition for the optional create table if missing 053 * setting. 054 */ 055 static final AttributeDefinition<Boolean> CREATE_TABLE_IF_MISSING = AttributeDefinition.builder("createTableIfMissing", Boolean.TRUE).build(); 056 057 058 /** 059 * The attribute definition for the optional create table ignore errors 060 * setting. 061 */ 062 static final AttributeDefinition<Boolean> CREATE_TABLE_IGNORE_ERRORS = AttributeDefinition.builder("createTableIgnoreErrors", Boolean.FALSE).build(); 063 064 065 /** 066 * The attribute definition for the optional connection pool reference. 067 */ 068 static final AttributeDefinition<String> CONNECTION_POOL = AttributeDefinition.builder("connectionPool", null, String.class).build(); 069 070 071 /** 072 * Returns the attribute definitions for the SQL store configuration. 073 * 074 * @return The attribute definitions. 075 */ 076 public static AttributeSet attributeDefinitionSet() { 077 return new AttributeSet(SQLStoreConfiguration.class, 078 AbstractStoreConfiguration.attributeDefinitionSet(), 079 RECORD_TRANSFORMER, 080 QUERY_EXECUTOR, 081 SQL_DIALECT, 082 CREATE_TABLE_IF_MISSING, 083 CREATE_TABLE_IGNORE_ERRORS, 084 CONNECTION_POOL 085 ); 086 } 087 088 089 /** 090 * The class for transforming between Infinispan entries (key / value 091 * pair and optional metadata) and a corresponding SQL record. 092 * 093 * <p>See {@link SQLRecordTransformer}. 094 */ 095 private final Attribute<Class> recordTransformerClass; 096 097 098 /** 099 * The optional class for executing direct SQL queries against the 100 * database. 101 * 102 * <p>See {@link com.nimbusds.infinispan.persistence.common.query.QueryExecutor} 103 */ 104 private final Attribute<Class> queryExecutorClass; 105 106 107 /** 108 * The configured SQL dialect. 109 */ 110 private final Attribute<SQLDialect> sqlDialect; 111 112 113 /** 114 * The configured optional create table if missing setting. 115 */ 116 private final Attribute<Boolean> createTableIfMissing; 117 118 119 /** 120 * The configured optional create table ignore errors setting. 121 */ 122 private final Attribute<Boolean> createTableIgnoreErrors; 123 124 125 /** 126 * The configured connection pool reference. 127 */ 128 private final Attribute<String> connectionPool; 129 130 131 /** 132 * Creates a new SQL store configuration. 133 * 134 * @param attributes The configuration attributes. Must not be 135 * {@code null}. 136 * @param asyncConfig Configuration for the async cache loader. 137 */ 138 public SQLStoreConfiguration(final AttributeSet attributes, 139 final AsyncStoreConfiguration asyncConfig) { 140 141 super(attributes, asyncConfig); 142 143 recordTransformerClass = attributes.attribute(RECORD_TRANSFORMER); 144 assert recordTransformerClass != null; 145 146 queryExecutorClass = attributes.attribute(QUERY_EXECUTOR); 147 148 sqlDialect = attributes.attribute(SQL_DIALECT); 149 assert sqlDialect != null; 150 151 createTableIfMissing = attributes.attribute(CREATE_TABLE_IF_MISSING); 152 153 createTableIgnoreErrors = attributes.attribute(CREATE_TABLE_IGNORE_ERRORS); 154 155 connectionPool = attributes.attribute(CONNECTION_POOL); 156 } 157 158 159 /** 160 * Returns the class for transforming between Infinispan entries (key / 161 * value pairs and optional metadata) and a corresponding SQL record. 162 * 163 * <p>See {@link SQLRecordTransformer}. 164 * 165 * @return The record transformer class. 166 */ 167 public Class getRecordTransformerClass() { 168 169 return recordTransformerClass.get(); 170 } 171 172 173 /** 174 * Returns the optional class for executing direct SQL queries against 175 * the database. 176 * 177 * <p>See {@link com.nimbusds.infinispan.persistence.common.query.QueryExecutor} 178 * 179 * @return The query executor class, {@code null} if not specified. 180 */ 181 public Class getQueryExecutorClass() { 182 183 return queryExecutorClass.get(); 184 } 185 186 187 /** 188 * Returns the configured SQL dialect. 189 * 190 * @return The SQL dialect. 191 */ 192 public SQLDialect getSQLDialect() { 193 194 return sqlDialect.get(); 195 } 196 197 198 /** 199 * Returns the configured create table if missing setting. 200 * 201 * @return {@code true} to create the underlying table(s) if missing, 202 * {@code false} to skip this check. 203 */ 204 public boolean createTableIfMissing() { 205 206 return createTableIfMissing.get(); 207 } 208 209 210 /** 211 * Returns the configured create table ignore error setting. 212 * 213 * @return {@code true} to ignore create table errors, {@code false} to 214 * treat them as fatal. 215 */ 216 public boolean createTableIgnoreErrors() { 217 218 return createTableIgnoreErrors.get(); 219 } 220 221 222 /** 223 * Returns the configured connection pool reference. 224 * 225 * @return The connection pool reference, {@code null} if none. 226 */ 227 public String getConnectionPool() { 228 229 return connectionPool.get(); 230 } 231 232 233 @Override 234 public Properties properties() { 235 236 // Interpolate with system properties where ${sysPropName} is found 237 238 var interpolatedProps = new Properties(); 239 240 for (String name: super.properties().stringPropertyNames()) { 241 interpolatedProps.setProperty(name, StringPropertyReplacer.replaceProperties(super.properties().getProperty(name))); 242 } 243 244 return interpolatedProps; 245 } 246 247 248 @Override 249 public void log() { 250 251 Loggers.MAIN_LOG.info("[IS0000] Infinispan SQL store: Record transformer class: {} ", getRecordTransformerClass().getCanonicalName()); 252 Loggers.MAIN_LOG.info("[IS0001] Infinispan SQL store: Query executor class: {} ", getQueryExecutorClass() != null ? getQueryExecutorClass().getCanonicalName() : "not specified"); 253 Loggers.MAIN_LOG.info("[IS0002] Infinispan SQL store: SQL dialect: {} ", sqlDialect); 254 Loggers.MAIN_LOG.info("[IS0004] Infinispan SQL store: Create table if missing: {} ", createTableIfMissing); 255 if (createTableIfMissing.get()) { 256 Loggers.MAIN_LOG.info("[IS0009] Infinispan SQL store: Create table ignore errors: {} ", createTableIgnoreErrors); 257 } 258 Loggers.MAIN_LOG.info("[IS0008] Infinispan SQL store: Connection pool reference: {} ", getConnectionPool() != null ? getConnectionPool() : "not specified"); 259 260 if (StringUtils.isNotBlank(properties().getProperty("dataSourceClassName"))) { 261 Loggers.MAIN_LOG.info("[IS0005] Infinispan SQL store: Data source class name: {} ", properties().getProperty("dataSourceClassName")); 262 } 263 264 if (StringUtils.isNotBlank(properties().getProperty("dataSource.url"))) { 265 Loggers.MAIN_LOG.info("[IS0006] Infinispan SQL store: Data source URL: {} ", properties().getProperty("dataSource.url")); 266 } 267 268 // Old style JDBC URL config 269 if (StringUtils.isNotBlank(properties().getProperty("jdbcUrl"))) { 270 Loggers.MAIN_LOG.info("[IS0003] Infinispan SQL store: JDBC URL: {} ", properties().getProperty("jdbcUrl")); 271 } 272 } 273}