001package com.nimbusds.infinispan.persistence.sql; 002 003 004import java.util.Properties; 005 006import com.nimbusds.common.config.ConfigurationException; 007import com.nimbusds.common.config.LoggableConfiguration; 008import com.thetransactioncompany.util.PropertyParseException; 009import com.thetransactioncompany.util.PropertyRetriever; 010import net.jcip.annotations.Immutable; 011import org.infinispan.commons.configuration.BuiltBy; 012import org.infinispan.commons.configuration.ConfigurationFor; 013import org.infinispan.commons.util.StringPropertyReplacer; 014import org.infinispan.configuration.cache.AbstractStoreConfiguration; 015import org.infinispan.configuration.cache.AsyncStoreConfiguration; 016import org.infinispan.configuration.cache.SingletonStoreConfiguration; 017import org.jooq.SQLDialect; 018 019 020/** 021 * SQL store configuration. 022 * 023 * <p>Example SQL store configuration: 024 * 025 * <pre> 026 * sqlStore.recordTransformer = com.nimbusds.infinispan.persistence.sql.UserEntityTransformer 027 * sqlStore.sqlDialect = H2 028 * </pre> 029 */ 030@Immutable 031@BuiltBy(SQLStoreConfigurationBuilder.class) 032@ConfigurationFor(SQLStore.class) 033public class SQLStoreConfiguration extends AbstractStoreConfiguration implements LoggableConfiguration { 034 035 036 /** 037 * The name of the class for transforming between Infinispan entries 038 * (key / value pair and optional metadata) and a corresponding SQL 039 * record. 040 * 041 * <p>See {@link SQLRecordTransformer}. 042 * 043 * <p>Property key: sqlStore.recordTransformer 044 */ 045 public final String recordTransformer; 046 047 048 /** 049 * The SQL dialect. 050 * 051 * <p>Property key: sqlStore.sqlDialect 052 */ 053 public final SQLDialect sqlDialect; 054 055 056 /** 057 * Creates a new SQL store configuration from the specified properties. 058 * All other settings assume defaults. 059 * 060 * @param properties The SQL store specific configuration properties. 061 * Must not be {@code null}. 062 */ 063 public SQLStoreConfiguration(final Properties properties) { 064 065 this( 066 false, // purgeOnStartup 067 false, // fetchPersistentState 068 false, // ignoreModifications 069 null, // AsyncStoreConfiguration 070 null, // SingletonStoreConfiguration 071 false, // preload 072 true, // shared 073 properties); 074 } 075 076 077 /** 078 * Creates a new SQL store configuration. 079 * 080 * @param purgeOnStartup If {@code true} the cache store will be 081 * purged when it starts up. 082 * @param fetchPersistentState If {@code true} the persistent state 083 * be fetched when joining a cluster. 084 * @param ignoreModifications If {@code true} any operation that 085 * modifies the cache (put, remove, clear, 086 * store...etc) won't be applied to the 087 * cache store. This means that the cache 088 * store could become out of sync with the 089 * cache. 090 * @param async Configuration for the async cache 091 * loader. 092 * @param singletonStore Configuration for a singleton store. 093 * @param preload If {@code true} when the cache starts 094 * data stored in the cache loader will be 095 * pre-loaded into memory. 096 * @param shared If {@code true} the cache store is 097 * shared among all cache instances. 098 * @param properties The SQL store specific configuration 099 * properties. Must not be {@code null}. 100 */ 101 public SQLStoreConfiguration(final boolean purgeOnStartup, 102 final boolean fetchPersistentState, 103 final boolean ignoreModifications, 104 final AsyncStoreConfiguration async, 105 final SingletonStoreConfiguration singletonStore, 106 final boolean preload, 107 final boolean shared, 108 final Properties properties) { 109 110 super( 111 purgeOnStartup, 112 fetchPersistentState, 113 ignoreModifications, 114 async, 115 singletonStore, 116 preload, 117 shared, 118 properties); 119 120 if (properties == null || properties.isEmpty()) { 121 throw new ConfigurationException("Missing SQL store configuration properties, check the service documentation"); 122 } 123 124 // Interpolate with system properties where ${sysPropName} is found 125 Properties interpolatedProps = new Properties(); 126 for (String name: properties.stringPropertyNames()) { 127 interpolatedProps.setProperty(name, StringPropertyReplacer.replaceProperties(properties.getProperty(name))); 128 } 129 130 PropertyRetriever pr = new PropertyRetriever(interpolatedProps); 131 132 try { 133 recordTransformer = pr.getString("sqlStore.recordTransformer"); 134 135 sqlDialect = SQLDialect.valueOf(SQLDialect.class, pr.getString("sqlStore.sqlDialect").toUpperCase()); 136 137 } catch (PropertyParseException e) { 138 throw new ConfigurationException(e.getMessage() + 139 ": Property: " + e.getPropertyKey() + 140 ": Value: " + e.getPropertyValue()); 141 } 142 } 143 144 145 @Override 146 public void log() { 147 148 Loggers.MAIN_LOG.info("[IS0000] Infinispan SQL store: Record transformer class: {} ", recordTransformer); 149 Loggers.MAIN_LOG.info("[IS0001] Infinispan SQL store: SQL dialect: {} ", sqlDialect); 150 Loggers.MAIN_LOG.info("[IS0002] Infinispan SQL store: JDBC URL: {} ", properties().getProperty("jdbcUrl")); 151 } 152}