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 * &lt;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"&gt;
033 *      
034 *      &lt;cache-container name="myCacheContainer" default-cache="myMap" statistics="true"&gt;
035 *              &lt;jmx duplicate-domains="true"/&gt;
036 *              &lt;local-cache name="myMap"&gt;
037 *                      &lt;eviction type="COUNT" size="100"/&gt;
038 *                      &lt;persistence passivation="false"&gt;
039 *                              &lt;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"&gt;
043 *
044 *                              &lt;property name="jdbcUrl"&gt;jdbc:h2:mem:test;DATABASE_TO_UPPER=false&lt;/property&gt;
045 *                              &lt;property name="username"&gt;admin&lt;/property&gt;
046 *                              &lt;property name="password"&gt;secret&lt;/property&gt;
047 *
048 *                              &lt;/sql-store&gt;
049 *                      &lt;/persistence&gt;
050 *              &lt;/local-cache&gt;
051 *      &lt;/cache-container&gt;
052 *      
053 * &lt;/infinispan&gt;
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}