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