View Javadoc

1   /**
2    * Copyright 2005-2006 the original author or authors.
3    *
4    * Licensed under the Gnu General Pubic License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    *
8    *      http://www.opensource.org/licenses/gpl-license.php
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13   * See the Gnu General Public License for more details.
14   */
15  package org.figure8.join.util;
16  
17  import org.figure8.join.core.ContainerContextHandler;
18  import org.figure8.join.core.InvalidParameterException;
19  
20  import org.apache.commons.logging.Log;
21  import net.sf.hibernate.Session;
22  import net.sf.hibernate.SessionFactory;
23  import net.sf.hibernate.HibernateException;
24  
25  import java.util.List;
26  import java.util.ArrayList;
27  /**
28   * An extension of thread that helps keeping Hibernate connections open.
29   * This hack is necessary for Hypersonic SQL that closes access to database
30   * if connections have been idle for too long !
31   * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
32   * @version $Revision: 1.2 $
33   */
34  public class ConnectionKeeper extends Thread{
35  
36     // Static -------------------------------------------------------------------
37  
38     /** Get a commons logger ... */
39     private static Log log = LogUtil.getLog(ConnectionKeeper.class);
40  
41  
42     // Attributes ---------------------------------------------------------------
43  
44     /** Number of connection to keep open */
45     private int numConnections;
46     /** Sleeping time in milliseconds */
47     private long sleepTime;
48     /** Flag telling if connections to keep are open */
49     private boolean open = false;
50  
51     /** List of opened connections to maintain */
52     private List connections = null;
53     /** Hibernate SessionFactory used to retrieve connections */
54     private SessionFactory sessionFactory = null;
55  
56  
57     // Constructors -------------------------------------------------------------
58  
59     /**
60      * Creates a new instance of ConnectionKeeper
61      * @param numConnections Number of connections to keep open
62      * @param sleepTime Sleeping time in milliseconds
63      * @throws InvalidParameterException if container context is not initialized
64      * and "sessionFactory" bean is not available yet.
65      */
66     public ConnectionKeeper(int numConnections, long sleepTime) throws InvalidParameterException{
67        // Initialize attributes.
68        this.numConnections = numConnections;
69        this.sleepTime = sleepTime;
70        this.open = true;
71        // Retrieve sessionFactory from context.
72        sessionFactory = (SessionFactory)ContainerContextHandler.getInstance().getComponent("sessionFactory");
73        connections = openConnections();
74     }
75  
76  
77     // Public -------------------------------------------------------------------
78  
79     /**
80      * Shutdown connection keeper thread.
81      */
82     public void shutdown(){
83        // Update and interrupt.
84        open = false;
85        interrupt();
86     }
87  
88  
89     // Override of Thread -------------------------------------------------------
90  
91     /**
92      * Run connection keeper thread.
93      */
94     public void run(){
95        while (true){
96           // Go out if closed.
97           if (!open)
98              break;
99           try{
100             // Else, start by sleeping.
101             Thread.sleep(sleepTime);
102          }
103          catch (InterruptedException ie){
104             if (open)
105                log.error("Thread interrupted.", ie);
106             else
107                log.info("Thread interrupted for shutdown.");
108          }
109          if (open){
110             // Close old connections, open new ones.
111             log.debug("Refreshing connections.");
112             List temp = connections;
113             connections = openConnections();
114             closeAllConnections(temp);
115             temp = null;
116          }
117       }
118       // Close connections before finishing.
119       closeAllConnections(connections);
120       log.debug("Finished.");
121    }
122 
123 
124    // Private -----------------------------------------------------------------
125 
126    /**
127     * Open a <b>numConnections</b> number of connections
128     * and put them into the returned list.
129     * @return List of open connections
130     */
131    private List openConnections(){
132       // Build a new list of connections.
133       List sessionList = new ArrayList();
134       Session session = null;
135       for (int i=0; i<numConnections; i++){
136          try{
137             session = sessionFactory.openSession();
138             session.connection();
139          }
140          catch (HibernateException e){
141             e.printStackTrace();
142          }
143          sessionList.add(session);
144          log.debug("Opened new connection.");
145       }
146       // Return this list.
147       return sessionList;
148     }
149 
150    /**
151     * Close connections contained in list
152     * @param connectionList The list of connections to close
153     */
154    private void closeAllConnections(List connectionList){
155       Session session = null;
156       for (int i=0; i<connectionList.size(); i++){
157          session = (Session)connectionList.get(i);
158          if (session != null && session.isConnected())
159             try{
160                session.close();
161                log.debug("Closed old session.");
162             }
163             catch (HibernateException e){
164                log.error("Error while closing session", e);
165             }
166             else log.warn("Connection was closed or not initialised properly.");
167         }
168     }
169 }