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
37
38 /** Get a commons logger ... */
39 private static Log log = LogUtil.getLog(ConnectionKeeper.class);
40
41
42
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
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
68 this.numConnections = numConnections;
69 this.sleepTime = sleepTime;
70 this.open = true;
71
72 sessionFactory = (SessionFactory)ContainerContextHandler.getInstance().getComponent("sessionFactory");
73 connections = openConnections();
74 }
75
76
77
78
79 /**
80 * Shutdown connection keeper thread.
81 */
82 public void shutdown(){
83
84 open = false;
85 interrupt();
86 }
87
88
89
90
91 /**
92 * Run connection keeper thread.
93 */
94 public void run(){
95 while (true){
96
97 if (!open)
98 break;
99 try{
100
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
111 log.debug("Refreshing connections.");
112 List temp = connections;
113 connections = openConnections();
114 closeAllConnections(temp);
115 temp = null;
116 }
117 }
118
119 closeAllConnections(connections);
120 log.debug("Finished.");
121 }
122
123
124
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
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
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 }