001package com.nimbusds.infinispan.persistence.sql.config; 002 003 004import java.util.Properties; 005 006import com.nimbusds.common.config.LoggableConfiguration; 007import com.nimbusds.infinispan.persistence.sql.Loggers; 008import com.nimbusds.infinispan.persistence.sql.SQLRecordTransformer; 009import com.nimbusds.infinispan.persistence.sql.SQLStore; 010import net.jcip.annotations.Immutable; 011import org.infinispan.commons.configuration.BuiltBy; 012import org.infinispan.commons.configuration.ConfigurationFor; 013import org.infinispan.commons.configuration.attributes.Attribute; 014import org.infinispan.commons.configuration.attributes.AttributeDefinition; 015import org.infinispan.commons.configuration.attributes.AttributeSet; 016import org.infinispan.commons.util.StringPropertyReplacer; 017import org.infinispan.configuration.cache.AbstractStoreConfiguration; 018import org.infinispan.configuration.cache.AsyncStoreConfiguration; 019import org.infinispan.configuration.cache.SingletonStoreConfiguration; 020import org.jooq.SQLDialect; 021 022 023/** 024 * SQL store configuration. 025 * 026 * <p>Example XML configuration: 027 * 028 * <pre> 029 * <infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 030 * xsi:schemaLocation="urn:infinispan:config:8.2 http://www.infinispan.org/schemas/infinispan-config-8.2.xsd" 031 * xmlns="urn:infinispan:config:8.2" 032 * xmlns:sql="urn:infinispan:config:store:sql:2.2"> 033 * 034 * <cache-container name="myCacheContainer" default-cache="myMap" statistics="true"> 035 * <jmx duplicate-domains="true"/> 036 * <local-cache name="myMap"> 037 * <eviction type="COUNT" size="100"/> 038 * <persistence passivation="false"> 039 * <sql-store xmlns="urn:infinispan:config:store:sql:2.2" 040 * shared="true" 041 * record-transformer="com.nimbusds.infinispan.persistence.sql.UserRecordTransformer" 042 * sql-dialect="H2"> 043 * 044 * <property name="jdbcUrl">jdbc:h2:mem:test;DATABASE_TO_UPPER=false</property> 045 * <property name="username">admin</property> 046 * <property name="password">secret</property> 047 * 048 * </sql-store> 049 * </persistence> 050 * </local-cache> 051 * </cache-container> 052 * 053 * </infinispan> 054 * </pre> 055 */ 056@Immutable 057@BuiltBy(SQLStoreConfigurationBuilder.class) 058@ConfigurationFor(SQLStore.class) 059public class SQLStoreConfiguration extends AbstractStoreConfiguration implements LoggableConfiguration { 060 061 062 /** 063 * The attribute definition for the record transformer class. 064 */ 065 static final AttributeDefinition<Class> RECORD_TRANSFORMER = AttributeDefinition.builder("recordTransformer", null, Class.class).build(); 066 067 068 /** 069 * The attribute definition for the query executor class. 070 */ 071 static final AttributeDefinition<Class> QUERY_EXECUTOR = AttributeDefinition.builder("queryExecutor", null, Class.class).build(); 072 073 074 /** 075 * The attribute definition for the SQL dialect. 076 */ 077 static final AttributeDefinition<SQLDialect> SQL_DIALECT = AttributeDefinition.builder("sqlDialect", SQLDialect.DEFAULT).build(); 078 079 080 /** 081 * Returns the attribute definitions for the SQL store configuration. 082 * 083 * @return The attribute definitions. 084 */ 085 public static AttributeSet attributeDefinitionSet() { 086 return new AttributeSet(SQLStoreConfiguration.class, 087 AbstractStoreConfiguration.attributeDefinitionSet(), 088 RECORD_TRANSFORMER, QUERY_EXECUTOR, SQL_DIALECT); 089 } 090 091 092 /** 093 * The class for transforming between Infinispan entries (key / value 094 * pair and optional metadata) and a corresponding SQL record. 095 * 096 * <p>See {@link SQLRecordTransformer}. 097 */ 098 private final Attribute<Class> recordTransformerClass; 099 100 101 /** 102 * The optional class for executing direct SQL queries against the 103 * database. 104 * 105 * <p>See {@link com.nimbusds.infinispan.persistence.common.query.QueryExecutor} 106 */ 107 private final Attribute<Class> queryExecutorClass; 108 109 110 /** 111 * The configured SQL dialect. 112 */ 113 private final Attribute<SQLDialect> sqlDialect; 114 115 116 /** 117 * Creates a new SQL store configuration. 118 * 119 * @param attributes The configuration attributes. Must not be 120 * {@code null}. 121 * @param asyncConfig Configuration for the async cache 122 * loader. 123 * @param singletonStoreConfig Configuration for a singleton store. 124 */ 125 public SQLStoreConfiguration(final AttributeSet attributes, 126 final AsyncStoreConfiguration asyncConfig, 127 final SingletonStoreConfiguration singletonStoreConfig) { 128 129 super(attributes, asyncConfig, singletonStoreConfig); 130 131 recordTransformerClass = attributes.attribute(RECORD_TRANSFORMER); 132 assert recordTransformerClass != null; 133 134 queryExecutorClass = attributes.attribute(QUERY_EXECUTOR); 135 136 sqlDialect = attributes.attribute(SQL_DIALECT); 137 assert sqlDialect != null; 138 } 139 140 141 /** 142 * Returns the class for transforming between Infinispan entries (key / 143 * value pairs and optional metadata) and a corresponding SQL record. 144 * 145 * <p>See {@link SQLRecordTransformer}. 146 * 147 * @return The record transformer class. 148 */ 149 public Class getRecordTransformerClass() { 150 151 return recordTransformerClass.get(); 152 } 153 154 155 /** 156 * Returns the optional class for executing direct SQL queries against 157 * the database. 158 * 159 * <p>See {@link com.nimbusds.infinispan.persistence.common.query.QueryExecutor} 160 * 161 * @return The query executor class, {@code null} if not specified. 162 */ 163 public Class getQueryExecutorClass() { 164 165 return queryExecutorClass.get(); 166 } 167 168 169 /** 170 * Returns the configured SQL dialect. 171 * 172 * @return The SQL dialect. 173 */ 174 public SQLDialect getSQLDialect() { 175 176 return sqlDialect.get(); 177 } 178 179 180 @Override 181 public Properties properties() { 182 183 // Interpolate with system properties where ${sysPropName} is found 184 185 Properties interpolatedProps = new Properties(); 186 187 for (String name: super.properties().stringPropertyNames()) { 188 interpolatedProps.setProperty(name, StringPropertyReplacer.replaceProperties(super.properties().getProperty(name))); 189 } 190 191 return interpolatedProps; 192 } 193 194 195 @Override 196 public void log() { 197 198 Loggers.MAIN_LOG.info("[IS0000] Infinispan SQL store: Record transformer class: {} ", getRecordTransformerClass().getCanonicalName()); 199 Loggers.MAIN_LOG.info("[IS0001] Infinispan SQL store: Query executor class: {} ", getQueryExecutorClass() != null ? getQueryExecutorClass().getCanonicalName() : "not specified"); 200 Loggers.MAIN_LOG.info("[IS0002] Infinispan SQL store: SQL dialect: {} ", sqlDialect); 201 Loggers.MAIN_LOG.info("[IS0003] Infinispan SQL store: JDBC URL: {} ", properties().getProperty("jdbcUrl")); 202 } 203}