View Javadoc

1   package org.apache.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.io.Serializable;
23  import java.sql.Connection;
24  import java.sql.DriverManager;
25  import java.sql.SQLException;
26  import java.sql.Statement;
27  import java.util.Collections;
28  import java.util.HashSet;
29  import java.util.Set;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.jcs.auxiliary.AuxiliaryCache;
34  import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
35  import org.apache.jcs.auxiliary.AuxiliaryCacheFactory;
36  import org.apache.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes;
37  import org.apache.jcs.auxiliary.disk.jdbc.JDBCDiskCacheManager;
38  import org.apache.jcs.engine.behavior.ICompositeCacheManager;
39  import org.apache.jcs.engine.behavior.IElementSerializer;
40  import org.apache.jcs.engine.control.CompositeCacheManager;
41  import org.apache.jcs.engine.logging.behavior.ICacheEventLogger;
42  
43  /**
44   * This factory should create mysql disk caches.
45   * <p>
46   * @author Aaron Smuts
47   */
48  public class HSQLDiskCacheFactory
49      implements AuxiliaryCacheFactory
50  {
51      /** The logger */
52      private final static Log log = LogFactory.getLog( HSQLDiskCacheFactory.class );
53  
54      /** Name for logging, etc. */
55      private String name = "HSQLDiskCacheFactory";
56  
57      /** The databases. */
58      private final Set<String> databases = Collections.synchronizedSet( new HashSet<String>() );
59  
60      /**
61       * This factory method should create an instance of the hsqlcache.
62       * <p>
63       * @param rawAttr
64       * @param arg1
65       * @param cacheEventLogger
66       * @param elementSerializer
67       * @return AuxiliaryCache
68       */
69      public <K extends Serializable, V extends Serializable> AuxiliaryCache<K, V> createCache( AuxiliaryCacheAttributes rawAttr, ICompositeCacheManager arg1,
70                                         ICacheEventLogger cacheEventLogger, IElementSerializer elementSerializer )
71      {
72          JDBCDiskCacheManager mgr = JDBCDiskCacheManager.getInstance( (JDBCDiskCacheAttributes) rawAttr,
73                                                                       CompositeCacheManager.getUnconfiguredInstance(),
74                                                                       cacheEventLogger, elementSerializer );
75          try
76          {
77              setupDatabase( (JDBCDiskCacheAttributes) rawAttr );
78          }
79          catch ( Exception e )
80          {
81              // TODO we may not want to try and get the cache at this point.
82              log.error( "Problem setting up database.", e );
83          }
84          return mgr.getCache( (JDBCDiskCacheAttributes) rawAttr );
85      }
86  
87      /**
88       * The name of the factory.
89       * <p>
90       * @param nameArg
91       */
92      public void setName( String nameArg )
93      {
94          name = nameArg;
95      }
96  
97      /**
98       * Returns the display name
99       * <p>
100      * @return name
101      */
102     public String getName()
103     {
104         return name;
105     }
106 
107     /**
108      * Creates the database if it doesn't exist, registers the driver class, etc.
109      * <p>
110      * @param attributes
111      * @throws Exception
112      */
113     protected void setupDatabase( JDBCDiskCacheAttributes attributes )
114         throws Exception
115     {
116         if ( attributes == null )
117         {
118             throw new Exception( "The attributes are null." );
119         }
120 
121         // url should start with "jdbc:hsqldb:"
122         String database = attributes.getUrl() + attributes.getDatabase();
123 
124         if ( databases.contains( database ) )
125         {
126             if ( log.isInfoEnabled() )
127             {
128                 log.info( "We already setup database [" + database + "]" );
129             }
130             return;
131         }
132 
133         // TODO get this from the attributes.
134         System.setProperty( "hsqldb.cache_scale", "8" );
135 
136         // "org.hsqldb.jdbcDriver"
137         String driver = attributes.getDriverClassName();
138         // "sa"
139         String user = attributes.getUserName();
140         // ""
141         String password = attributes.getPassword();
142 
143         new org.hsqldb.jdbcDriver();
144         try
145         {
146             Class.forName( driver ).newInstance();
147 
148             Connection cConn = DriverManager.getConnection( database, user, password );
149 
150             setupTABLE( cConn, attributes.getTableName() );
151 
152             if ( log.isInfoEnabled() )
153             {
154                 log.info( "Finished setting up database [" + database + "]" );
155             }
156 
157             databases.add( database );
158         }
159         catch ( Exception e )
160         {
161             log.error( "Fatal problem setting up the database.", e );
162         }
163     }
164 
165     /**
166      * SETUP TABLE FOR CACHE
167      * <p>
168      * @param cConn
169      * @param tableName
170      */
171     private void setupTABLE( Connection cConn, String tableName ) throws SQLException
172     {
173         boolean newT = true;
174 
175         // TODO make the cached nature of the table configurable
176         StringBuffer createSql = new StringBuffer();
177         createSql.append( "CREATE CACHED TABLE " + tableName );
178         createSql.append( "( " );
179         createSql.append( "CACHE_KEY             VARCHAR(250)          NOT NULL, " );
180         createSql.append( "REGION                VARCHAR(250)          NOT NULL, " );
181         createSql.append( "ELEMENT               BINARY, " );
182         createSql.append( "CREATE_TIME           DATE, " );
183         createSql.append( "CREATE_TIME_SECONDS   BIGINT, " );
184         createSql.append( "MAX_LIFE_SECONDS      BIGINT, " );
185         createSql.append( "SYSTEM_EXPIRE_TIME_SECONDS      BIGINT, " );
186         createSql.append( "IS_ETERNAL            CHAR(1), " );
187         createSql.append( "PRIMARY KEY (CACHE_KEY, REGION) " );
188         createSql.append( ");" );
189 
190         Statement sStatement = cConn.createStatement();
191 
192         try
193         {
194             sStatement.executeQuery( createSql.toString() );
195             sStatement.close();
196         }
197         catch ( SQLException e )
198         {
199             // FIXME: This is not reliable
200             if ( e.toString().indexOf( "already exists" ) != -1 )
201             {
202                 newT = false;
203             }
204             else
205             {
206                 throw e;
207             }
208         }
209 
210         // TODO create an index on SYSTEM_EXPIRE_TIME_SECONDS
211         String setupData[] = { "create index iKEY on " + tableName + " (CACHE_KEY, REGION)" };
212 
213         if ( newT )
214         {
215             for ( int i = 1; i < setupData.length; i++ )
216             {
217                 try
218                 {
219                     sStatement.executeQuery( setupData[i] );
220                 }
221                 catch ( SQLException e )
222                 {
223                     log.error( "Exception caught when creating index." + e );
224                 }
225             }
226         }
227     }
228 }