View Javadoc
1   package org.apache.commons.jcs.auxiliary.disk.jdbc.hsql;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.sql.Connection;
23  import java.sql.DriverManager;
24  import java.sql.SQLException;
25  import java.sql.Statement;
26  import java.util.Collections;
27  import java.util.HashSet;
28  import java.util.Set;
29  
30  import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
31  import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCache;
32  import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes;
33  import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheFactory;
34  import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager;
35  import org.apache.commons.jcs.engine.behavior.IElementSerializer;
36  import org.apache.commons.jcs.engine.logging.behavior.ICacheEventLogger;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /**
41   * This factory should create hsql disk caches.
42   * <p>
43   * @author Aaron Smuts
44   */
45  public class HSQLDiskCacheFactory
46      extends JDBCDiskCacheFactory
47  {
48      /** The logger */
49      private static final Log log = LogFactory.getLog( HSQLDiskCacheFactory.class );
50  
51      /** The databases. */
52      private Set<String> databases;
53  
54      /**
55       * This factory method should create an instance of the hsqlcache.
56       * <p>
57       * @param rawAttr
58       * @param compositeCacheManager
59       * @param cacheEventLogger
60       * @param elementSerializer
61       * @return JDBCDiskCache
62       * @throws SQLException if the creation of the cache instance fails
63       */
64      @Override
65      public <K, V> JDBCDiskCache<K, V> createCache( AuxiliaryCacheAttributes rawAttr,
66  			ICompositeCacheManager compositeCacheManager,
67  			ICacheEventLogger cacheEventLogger,
68  			IElementSerializer elementSerializer )
69  			throws SQLException
70      {
71          setupDatabase( (JDBCDiskCacheAttributes) rawAttr );
72          return super.createCache(rawAttr, compositeCacheManager, cacheEventLogger, elementSerializer);
73      }
74  
75      /**
76       * Initialize this factory
77       */
78      @Override
79      public void initialize()
80      {
81          super.initialize();
82          this.databases = Collections.synchronizedSet( new HashSet<String>() );
83      }
84  
85      /**
86       * Creates the database if it doesn't exist, registers the driver class, etc.
87       * <p>
88       * @param attributes
89       * @throws SQLException
90       */
91      protected void setupDatabase( JDBCDiskCacheAttributes attributes )
92          throws SQLException
93      {
94          if ( attributes == null )
95          {
96              throw new SQLException( "The attributes are null." );
97          }
98  
99          // url should start with "jdbc:hsqldb:"
100         String database = attributes.getUrl() + attributes.getDatabase();
101 
102         if ( databases.contains( database ) )
103         {
104             if ( log.isInfoEnabled() )
105             {
106                 log.info( "We already setup database [" + database + "]" );
107             }
108             return;
109         }
110 
111         // TODO get this from the attributes.
112         System.setProperty( "hsqldb.cache_scale", "8" );
113 
114         // "org.hsqldb.jdbcDriver"
115         String driver = attributes.getDriverClassName();
116         // "sa"
117         String user = attributes.getUserName();
118         // ""
119         String password = attributes.getPassword();
120 
121         try
122         {
123             Class.forName( driver ).newInstance();
124         }
125         catch (Exception e)
126         {
127             throw new SQLException( "Could not initialize driver " + driver, e );
128         }
129 
130         Connection cConn = DriverManager.getConnection( database, user, password );
131         setupTable( cConn, attributes.getTableName() );
132 
133         if ( log.isInfoEnabled() )
134         {
135             log.info( "Finished setting up database [" + database + "]" );
136         }
137 
138         databases.add( database );
139     }
140 
141     /**
142      * SETUP TABLE FOR CACHE
143      * <p>
144      * @param cConn
145      * @param tableName
146      */
147     protected void setupTable( Connection cConn, String tableName ) throws SQLException
148     {
149         // TODO make the cached nature of the table configurable
150         StringBuilder createSql = new StringBuilder();
151         createSql.append( "CREATE CACHED TABLE ").append( tableName );
152         createSql.append( "( " );
153         createSql.append( "CACHE_KEY             VARCHAR(250)          NOT NULL, " );
154         createSql.append( "REGION                VARCHAR(250)          NOT NULL, " );
155         createSql.append( "ELEMENT               BINARY, " );
156         createSql.append( "CREATE_TIME           TIMESTAMP, " );
157         createSql.append( "UPDATE_TIME_SECONDS   BIGINT, " );
158         createSql.append( "MAX_LIFE_SECONDS      BIGINT, " );
159         createSql.append( "SYSTEM_EXPIRE_TIME_SECONDS      BIGINT, " );
160         createSql.append( "IS_ETERNAL            CHAR(1), " );
161         createSql.append( "PRIMARY KEY (CACHE_KEY, REGION) " );
162         createSql.append( ");" );
163 
164         Statement sStatement = cConn.createStatement();
165 
166         try
167         {
168             sStatement.execute( createSql.toString() );
169         }
170         catch ( SQLException e )
171         {
172             if (!"23000".equals(e.getSQLState()))
173             {
174                 throw e;
175             }
176         }
177         finally
178         {
179             sStatement.close();
180         }
181     }
182 }