1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.catalina.session;
19
20 import org.apache.catalina.Container;
21 import org.apache.catalina.LifecycleException;
22 import org.apache.catalina.Loader;
23 import org.apache.catalina.Session;
24 import org.apache.catalina.Store;
25 import org.apache.catalina.util.CustomObjectInputStream;
26 import java.io.BufferedInputStream;
27 import java.io.BufferedOutputStream;
28 import java.io.ByteArrayInputStream;
29 import java.io.ByteArrayOutputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.ObjectInputStream;
33 import java.io.ObjectOutputStream;
34 import java.sql.Connection;
35 import java.sql.Driver;
36 import java.sql.PreparedStatement;
37 import java.sql.ResultSet;
38 import java.sql.SQLException;
39 import java.util.ArrayList;
40 import java.util.Properties;
41
42 /**
43 * Implementation of the <code>Store</code> interface that stores
44 * serialized session objects in a database. Sessions that are
45 * saved are still subject to being expired based on inactivity.
46 *
47 * @author Bip Thelin
48 * @version $Revision: 554109 $, $Date: 2007-07-07 03:40:19 +0200 (sam., 07 juil. 2007) $
49 */
50
51 public class JDBCStore
52 extends StoreBase implements Store {
53
54 /**
55 * The descriptive information about this implementation.
56 */
57 protected static String info = "JDBCStore/1.0";
58
59 /**
60 * Context name associated with this Store
61 */
62 private String name = null;
63
64 /**
65 * Name to register for this Store, used for logging.
66 */
67 protected static String storeName = "JDBCStore";
68
69 /**
70 * Name to register for the background thread.
71 */
72 protected String threadName = "JDBCStore";
73
74 /**
75 * The connection username to use when trying to connect to the database.
76 */
77 protected String connectionName = null;
78
79
80 /**
81 * The connection URL to use when trying to connect to the database.
82 */
83 protected String connectionPassword = null;
84
85 /**
86 * Connection string to use when connecting to the DB.
87 */
88 protected String connectionURL = null;
89
90 /**
91 * The database connection.
92 */
93 private Connection dbConnection = null;
94
95 /**
96 * Instance of the JDBC Driver class we use as a connection factory.
97 */
98 protected Driver driver = null;
99
100 /**
101 * Driver to use.
102 */
103 protected String driverName = null;
104
105 // ------------------------------------------------------------- Table & cols
106
107 /**
108 * Table to use.
109 */
110 protected String sessionTable = "tomcat$sessions";
111
112 /**
113 * Column to use for /Engine/Host/Context name
114 */
115 protected String sessionAppCol = "app";
116
117 /**
118 * Id column to use.
119 */
120 protected String sessionIdCol = "id";
121
122 /**
123 * Data column to use.
124 */
125 protected String sessionDataCol = "data";
126
127 /**
128 * Is Valid column to use.
129 */
130 protected String sessionValidCol = "valid";
131
132 /**
133 * Max Inactive column to use.
134 */
135 protected String sessionMaxInactiveCol = "maxinactive";
136
137 /**
138 * Last Accessed column to use.
139 */
140 protected String sessionLastAccessedCol = "lastaccess";
141
142 // ------------------------------------------------------------- SQL Variables
143
144 /**
145 * Variable to hold the <code>getSize()</code> prepared statement.
146 */
147 protected PreparedStatement preparedSizeSql = null;
148
149 /**
150 * Variable to hold the <code>keys()</code> prepared statement.
151 */
152 protected PreparedStatement preparedKeysSql = null;
153
154 /**
155 * Variable to hold the <code>save()</code> prepared statement.
156 */
157 protected PreparedStatement preparedSaveSql = null;
158
159 /**
160 * Variable to hold the <code>clear()</code> prepared statement.
161 */
162 protected PreparedStatement preparedClearSql = null;
163
164 /**
165 * Variable to hold the <code>remove()</code> prepared statement.
166 */
167 protected PreparedStatement preparedRemoveSql = null;
168
169 /**
170 * Variable to hold the <code>load()</code> prepared statement.
171 */
172 protected PreparedStatement preparedLoadSql = null;
173
174 // ------------------------------------------------------------- Properties
175
176 /**
177 * Return the info for this Store.
178 */
179 public String getInfo() {
180 return (info);
181 }
182
183 /**
184 * Return the name for this instance (built from container name)
185 */
186 public String getName() {
187 if (name == null) {
188 Container container = manager.getContainer();
189 String contextName = container.getName();
190 String hostName = "";
191 String engineName = "";
192
193 if (container.getParent() != null) {
194 Container host = container.getParent();
195 hostName = host.getName();
196 if (host.getParent() != null) {
197 engineName = host.getParent().getName();
198 }
199 }
200 name = "/" + engineName + "/" + hostName + contextName;
201 }
202 return name;
203 }
204
205 /**
206 * Return the thread name for this Store.
207 */
208 public String getThreadName() {
209 return (threadName);
210 }
211
212 /**
213 * Return the name for this Store, used for logging.
214 */
215 public String getStoreName() {
216 return (storeName);
217 }
218
219 /**
220 * Set the driver for this Store.
221 *
222 * @param driverName The new driver
223 */
224 public void setDriverName(String driverName) {
225 String oldDriverName = this.driverName;
226 this.driverName = driverName;
227 support.firePropertyChange("driverName",
228 oldDriverName,
229 this.driverName);
230 this.driverName = driverName;
231 }
232
233 /**
234 * Return the driver for this Store.
235 */
236 public String getDriverName() {
237 return (this.driverName);
238 }
239
240 /**
241 * Return the username to use to connect to the database.
242 *
243 */
244 public String getConnectionName() {
245 return connectionName;
246 }
247
248 /**
249 * Set the username to use to connect to the database.
250 *
251 * @param connectionName Username
252 */
253 public void setConnectionName(String connectionName) {
254 this.connectionName = connectionName;
255 }
256
257 /**
258 * Return the password to use to connect to the database.
259 *
260 */
261 public String getConnectionPassword() {
262 return connectionPassword;
263 }
264
265 /**
266 * Set the password to use to connect to the database.
267 *
268 * @param connectionPassword User password
269 */
270 public void setConnectionPassword(String connectionPassword) {
271 this.connectionPassword = connectionPassword;
272 }
273
274 /**
275 * Set the Connection URL for this Store.
276 *
277 * @param connectionURL The new Connection URL
278 */
279 public void setConnectionURL(String connectionURL) {
280 String oldConnString = this.connectionURL;
281 this.connectionURL = connectionURL;
282 support.firePropertyChange("connectionURL",
283 oldConnString,
284 this.connectionURL);
285 }
286
287 /**
288 * Return the Connection URL for this Store.
289 */
290 public String getConnectionURL() {
291 return (this.connectionURL);
292 }
293
294 /**
295 * Set the table for this Store.
296 *
297 * @param sessionTable The new table
298 */
299 public void setSessionTable(String sessionTable) {
300 String oldSessionTable = this.sessionTable;
301 this.sessionTable = sessionTable;
302 support.firePropertyChange("sessionTable",
303 oldSessionTable,
304 this.sessionTable);
305 }
306
307 /**
308 * Return the table for this Store.
309 */
310 public String getSessionTable() {
311 return (this.sessionTable);
312 }
313
314 /**
315 * Set the App column for the table.
316 *
317 * @param sessionAppCol the column name
318 */
319 public void setSessionAppCol(String sessionAppCol) {
320 String oldSessionAppCol = this.sessionAppCol;
321 this.sessionAppCol = sessionAppCol;
322 support.firePropertyChange("sessionAppCol",
323 oldSessionAppCol,
324 this.sessionAppCol);
325 }
326
327 /**
328 * Return the web application name column for the table.
329 */
330 public String getSessionAppCol() {
331 return (this.sessionAppCol);
332 }
333
334 /**
335 * Set the Id column for the table.
336 *
337 * @param sessionIdCol the column name
338 */
339 public void setSessionIdCol(String sessionIdCol) {
340 String oldSessionIdCol = this.sessionIdCol;
341 this.sessionIdCol = sessionIdCol;
342 support.firePropertyChange("sessionIdCol",
343 oldSessionIdCol,
344 this.sessionIdCol);
345 }
346
347 /**
348 * Return the Id column for the table.
349 */
350 public String getSessionIdCol() {
351 return (this.sessionIdCol);
352 }
353
354 /**
355 * Set the Data column for the table
356 *
357 * @param sessionDataCol the column name
358 */
359 public void setSessionDataCol(String sessionDataCol) {
360 String oldSessionDataCol = this.sessionDataCol;
361 this.sessionDataCol = sessionDataCol;
362 support.firePropertyChange("sessionDataCol",
363 oldSessionDataCol,
364 this.sessionDataCol);
365 }
366
367 /**
368 * Return the data column for the table
369 */
370 public String getSessionDataCol() {
371 return (this.sessionDataCol);
372 }
373
374 /**
375 * Set the Is Valid column for the table
376 *
377 * @param sessionValidCol The column name
378 */
379 public void setSessionValidCol(String sessionValidCol) {
380 String oldSessionValidCol = this.sessionValidCol;
381 this.sessionValidCol = sessionValidCol;
382 support.firePropertyChange("sessionValidCol",
383 oldSessionValidCol,
384 this.sessionValidCol);
385 }
386
387 /**
388 * Return the Is Valid column
389 */
390 public String getSessionValidCol() {
391 return (this.sessionValidCol);
392 }
393
394 /**
395 * Set the Max Inactive column for the table
396 *
397 * @param sessionMaxInactiveCol The column name
398 */
399 public void setSessionMaxInactiveCol(String sessionMaxInactiveCol) {
400 String oldSessionMaxInactiveCol = this.sessionMaxInactiveCol;
401 this.sessionMaxInactiveCol = sessionMaxInactiveCol;
402 support.firePropertyChange("sessionMaxInactiveCol",
403 oldSessionMaxInactiveCol,
404 this.sessionMaxInactiveCol);
405 }
406
407 /**
408 * Return the Max Inactive column
409 */
410 public String getSessionMaxInactiveCol() {
411 return (this.sessionMaxInactiveCol);
412 }
413
414 /**
415 * Set the Last Accessed column for the table
416 *
417 * @param sessionLastAccessedCol The column name
418 */
419 public void setSessionLastAccessedCol(String sessionLastAccessedCol) {
420 String oldSessionLastAccessedCol = this.sessionLastAccessedCol;
421 this.sessionLastAccessedCol = sessionLastAccessedCol;
422 support.firePropertyChange("sessionLastAccessedCol",
423 oldSessionLastAccessedCol,
424 this.sessionLastAccessedCol);
425 }
426
427 /**
428 * Return the Last Accessed column
429 */
430 public String getSessionLastAccessedCol() {
431 return (this.sessionLastAccessedCol);
432 }
433
434 // --------------------------------------------------------- Public Methods
435
436 /**
437 * Return an array containing the session identifiers of all Sessions
438 * currently saved in this Store. If there are no such Sessions, a
439 * zero-length array is returned.
440 *
441 * @exception IOException if an input/output error occurred
442 */
443 public String[] keys() throws IOException {
444 ResultSet rst = null;
445 String keys[] = null;
446 synchronized (this) {
447 int numberOfTries = 2;
448 while (numberOfTries > 0) {
449
450 Connection _conn = getConnection();
451 if (_conn == null) {
452 return (new String[0]);
453 }
454 try {
455 if (preparedKeysSql == null) {
456 String keysSql = "SELECT " + sessionIdCol + " FROM "
457 + sessionTable + " WHERE " + sessionAppCol
458 + " = ?";
459 preparedKeysSql = _conn.prepareStatement(keysSql);
460 }
461
462 preparedKeysSql.setString(1, getName());
463 rst = preparedKeysSql.executeQuery();
464 ArrayList tmpkeys = new ArrayList();
465 if (rst != null) {
466 while (rst.next()) {
467 tmpkeys.add(rst.getString(1));
468 }
469 }
470 keys = (String[]) tmpkeys.toArray(new String[tmpkeys.size()]);
471 // Break out after the finally block
472 numberOfTries = 0;
473 } catch (SQLException e) {
474 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
475 keys = new String[0];
476 // Close the connection so that it gets reopened next time
477 if (dbConnection != null)
478 close(dbConnection);
479 } finally {
480 try {
481 if (rst != null) {
482 rst.close();
483 }
484 } catch (SQLException e) {
485 ;
486 }
487
488 release(_conn);
489 }
490 numberOfTries--;
491 }
492 }
493
494 return (keys);
495 }
496
497 /**
498 * Return an integer containing a count of all Sessions
499 * currently saved in this Store. If there are no Sessions,
500 * <code>0</code> is returned.
501 *
502 * @exception IOException if an input/output error occurred
503 */
504 public int getSize() throws IOException {
505 int size = 0;
506 ResultSet rst = null;
507
508 synchronized (this) {
509 int numberOfTries = 2;
510 while (numberOfTries > 0) {
511 Connection _conn = getConnection();
512
513 if (_conn == null) {
514 return (size);
515 }
516
517 try {
518 if (preparedSizeSql == null) {
519 String sizeSql = "SELECT COUNT(" + sessionIdCol
520 + ") FROM " + sessionTable + " WHERE "
521 + sessionAppCol + " = ?";
522 preparedSizeSql = _conn.prepareStatement(sizeSql);
523 }
524
525 preparedSizeSql.setString(1, getName());
526 rst = preparedSizeSql.executeQuery();
527 if (rst.next()) {
528 size = rst.getInt(1);
529 }
530 // Break out after the finally block
531 numberOfTries = 0;
532 } catch (SQLException e) {
533 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
534 if (dbConnection != null)
535 close(dbConnection);
536 } finally {
537 try {
538 if (rst != null)
539 rst.close();
540 } catch (SQLException e) {
541 ;
542 }
543
544 release(_conn);
545 }
546 numberOfTries--;
547 }
548 }
549 return (size);
550 }
551
552 /**
553 * Load the Session associated with the id <code>id</code>.
554 * If no such session is found <code>null</code> is returned.
555 *
556 * @param id a value of type <code>String</code>
557 * @return the stored <code>Session</code>
558 * @exception ClassNotFoundException if an error occurs
559 * @exception IOException if an input/output error occurred
560 */
561 public Session load(String id)
562 throws ClassNotFoundException, IOException {
563 ResultSet rst = null;
564 StandardSession _session = null;
565 Loader loader = null;
566 ClassLoader classLoader = null;
567 ObjectInputStream ois = null;
568 BufferedInputStream bis = null;
569 Container container = manager.getContainer();
570
571 synchronized (this) {
572 int numberOfTries = 2;
573 while (numberOfTries > 0) {
574 Connection _conn = getConnection();
575 if (_conn == null) {
576 return (null);
577 }
578
579 try {
580 if (preparedLoadSql == null) {
581 String loadSql = "SELECT " + sessionIdCol + ", "
582 + sessionDataCol + " FROM " + sessionTable
583 + " WHERE " + sessionIdCol + " = ? AND "
584 + sessionAppCol + " = ?";
585 preparedLoadSql = _conn.prepareStatement(loadSql);
586 }
587
588 preparedLoadSql.setString(1, id);
589 preparedLoadSql.setString(2, getName());
590 rst = preparedLoadSql.executeQuery();
591 if (rst.next()) {
592 bis = new BufferedInputStream(rst.getBinaryStream(2));
593
594 if (container != null) {
595 loader = container.getLoader();
596 }
597 if (loader != null) {
598 classLoader = loader.getClassLoader();
599 }
600 if (classLoader != null) {
601 ois = new CustomObjectInputStream(bis,
602 classLoader);
603 } else {
604 ois = new ObjectInputStream(bis);
605 }
606
607 if (manager.getContainer().getLogger().isDebugEnabled()) {
608 manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".loading",
609 id, sessionTable));
610 }
611
612 _session = (StandardSession) manager.createEmptySession();
613 _session.readObjectData(ois);
614 _session.setManager(manager);
615 } else if (manager.getContainer().getLogger().isDebugEnabled()) {
616 manager.getContainer().getLogger().debug(getStoreName() + ": No persisted data object found");
617 }
618 // Break out after the finally block
619 numberOfTries = 0;
620 } catch (SQLException e) {
621 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
622 if (dbConnection != null)
623 close(dbConnection);
624 } finally {
625 try {
626 if (rst != null) {
627 rst.close();
628 }
629 } catch (SQLException e) {
630 ;
631 }
632 if (ois != null) {
633 try {
634 ois.close();
635 } catch (IOException e) {
636 ;
637 }
638 }
639 release(_conn);
640 }
641 numberOfTries--;
642 }
643 }
644
645 return (_session);
646 }
647
648 /**
649 * Remove the Session with the specified session identifier from
650 * this Store, if present. If no such Session is present, this method
651 * takes no action.
652 *
653 * @param id Session identifier of the Session to be removed
654 *
655 * @exception IOException if an input/output error occurs
656 */
657 public void remove(String id) throws IOException {
658
659 synchronized (this) {
660 int numberOfTries = 2;
661 while (numberOfTries > 0) {
662 Connection _conn = getConnection();
663
664 if (_conn == null) {
665 return;
666 }
667
668 try {
669 if (preparedRemoveSql == null) {
670 String removeSql = "DELETE FROM " + sessionTable
671 + " WHERE " + sessionIdCol + " = ? AND "
672 + sessionAppCol + " = ?";
673 preparedRemoveSql = _conn.prepareStatement(removeSql);
674 }
675
676 preparedRemoveSql.setString(1, id);
677 preparedRemoveSql.setString(2, getName());
678 preparedRemoveSql.execute();
679 // Break out after the finally block
680 numberOfTries = 0;
681 } catch (SQLException e) {
682 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
683 if (dbConnection != null)
684 close(dbConnection);
685 } finally {
686 release(_conn);
687 }
688 numberOfTries--;
689 }
690 }
691
692 if (manager.getContainer().getLogger().isDebugEnabled()) {
693 manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".removing", id, sessionTable));
694 }
695 }
696
697 /**
698 * Remove all of the Sessions in this Store.
699 *
700 * @exception IOException if an input/output error occurs
701 */
702 public void clear() throws IOException {
703
704 synchronized (this) {
705 int numberOfTries = 2;
706 while (numberOfTries > 0) {
707 Connection _conn = getConnection();
708 if (_conn == null) {
709 return;
710 }
711
712 try {
713 if (preparedClearSql == null) {
714 String clearSql = "DELETE FROM " + sessionTable
715 + " WHERE " + sessionAppCol + " = ?";
716 preparedClearSql = _conn.prepareStatement(clearSql);
717 }
718
719 preparedClearSql.setString(1, getName());
720 preparedClearSql.execute();
721 // Break out after the finally block
722 numberOfTries = 0;
723 } catch (SQLException e) {
724 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
725 if (dbConnection != null)
726 close(dbConnection);
727 } finally {
728 release(_conn);
729 }
730 numberOfTries--;
731 }
732 }
733 }
734
735 /**
736 * Save a session to the Store.
737 *
738 * @param session the session to be stored
739 * @exception IOException if an input/output error occurs
740 */
741 public void save(Session session) throws IOException {
742 ObjectOutputStream oos = null;
743 ByteArrayOutputStream bos = null;
744 ByteArrayInputStream bis = null;
745 InputStream in = null;
746
747 synchronized (this) {
748 int numberOfTries = 2;
749 while (numberOfTries > 0) {
750 Connection _conn = getConnection();
751 if (_conn == null) {
752 return;
753 }
754
755 // If sessions already exist in DB, remove and insert again.
756 // TODO:
757 // * Check if ID exists in database and if so use UPDATE.
758 remove(session.getIdInternal());
759
760 try {
761 bos = new ByteArrayOutputStream();
762 oos = new ObjectOutputStream(new BufferedOutputStream(bos));
763
764 ((StandardSession) session).writeObjectData(oos);
765 oos.close();
766 oos = null;
767 byte[] obs = bos.toByteArray();
768 int size = obs.length;
769 bis = new ByteArrayInputStream(obs, 0, size);
770 in = new BufferedInputStream(bis, size);
771
772 if (preparedSaveSql == null) {
773 String saveSql = "INSERT INTO " + sessionTable + " ("
774 + sessionIdCol + ", " + sessionAppCol + ", "
775 + sessionDataCol + ", " + sessionValidCol
776 + ", " + sessionMaxInactiveCol + ", "
777 + sessionLastAccessedCol
778 + ") VALUES (?, ?, ?, ?, ?, ?)";
779 preparedSaveSql = _conn.prepareStatement(saveSql);
780 }
781
782 preparedSaveSql.setString(1, session.getIdInternal());
783 preparedSaveSql.setString(2, getName());
784 preparedSaveSql.setBinaryStream(3, in, size);
785 preparedSaveSql.setString(4, session.isValid() ? "1" : "0");
786 preparedSaveSql.setInt(5, session.getMaxInactiveInterval());
787 preparedSaveSql.setLong(6, session.getLastAccessedTime());
788 preparedSaveSql.execute();
789 // Break out after the finally block
790 numberOfTries = 0;
791 } catch (SQLException e) {
792 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".SQLException", e));
793 if (dbConnection != null)
794 close(dbConnection);
795 } catch (IOException e) {
796 ;
797 } finally {
798 if (oos != null) {
799 oos.close();
800 }
801 if (bis != null) {
802 bis.close();
803 }
804 if (in != null) {
805 in.close();
806 }
807
808 release(_conn);
809 }
810 numberOfTries--;
811 }
812 }
813
814 if (manager.getContainer().getLogger().isDebugEnabled()) {
815 manager.getContainer().getLogger().debug(sm.getString(getStoreName() + ".saving",
816 session.getIdInternal(), sessionTable));
817 }
818 }
819
820 // --------------------------------------------------------- Protected Methods
821
822 /**
823 * Check the connection associated with this store, if it's
824 * <code>null</code> or closed try to reopen it.
825 * Returns <code>null</code> if the connection could not be established.
826 *
827 * @return <code>Connection</code> if the connection suceeded
828 */
829 protected Connection getConnection() {
830 try {
831 if (dbConnection == null || dbConnection.isClosed()) {
832 manager.getContainer().getLogger().info(sm.getString(getStoreName() + ".checkConnectionDBClosed"));
833 open();
834 if (dbConnection == null || dbConnection.isClosed()) {
835 manager.getContainer().getLogger().info(sm.getString(getStoreName() + ".checkConnectionDBReOpenFail"));
836 }
837 }
838 } catch (SQLException ex) {
839 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".checkConnectionSQLException",
840 ex.toString()));
841 }
842
843 return dbConnection;
844 }
845
846 /**
847 * Open (if necessary) and return a database connection for use by
848 * this Realm.
849 *
850 * @exception SQLException if a database error occurs
851 */
852 protected Connection open() throws SQLException {
853
854 // Do nothing if there is a database connection already open
855 if (dbConnection != null)
856 return (dbConnection);
857
858 // Instantiate our database driver if necessary
859 if (driver == null) {
860 try {
861 Class clazz = Class.forName(driverName);
862 driver = (Driver) clazz.newInstance();
863 } catch (ClassNotFoundException ex) {
864 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".checkConnectionClassNotFoundException",
865 ex.toString()));
866 } catch (InstantiationException ex) {
867 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".checkConnectionClassNotFoundException",
868 ex.toString()));
869 } catch (IllegalAccessException ex) {
870 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".checkConnectionClassNotFoundException",
871 ex.toString()));
872 }
873 }
874
875 // Open a new connection
876 Properties props = new Properties();
877 if (connectionName != null)
878 props.put("user", connectionName);
879 if (connectionPassword != null)
880 props.put("password", connectionPassword);
881 dbConnection = driver.connect(connectionURL, props);
882 dbConnection.setAutoCommit(true);
883 return (dbConnection);
884
885 }
886
887 /**
888 * Close the specified database connection.
889 *
890 * @param dbConnection The connection to be closed
891 */
892 protected void close(Connection dbConnection) {
893
894 // Do nothing if the database connection is already closed
895 if (dbConnection == null)
896 return;
897
898 // Close our prepared statements (if any)
899 try {
900 preparedSizeSql.close();
901 } catch (Throwable f) {
902 ;
903 }
904 this.preparedSizeSql = null;
905
906 try {
907 preparedKeysSql.close();
908 } catch (Throwable f) {
909 ;
910 }
911 this.preparedKeysSql = null;
912
913 try {
914 preparedSaveSql.close();
915 } catch (Throwable f) {
916 ;
917 }
918 this.preparedSaveSql = null;
919
920 try {
921 preparedClearSql.close();
922 } catch (Throwable f) {
923 ;
924 }
925
926 try {
927 preparedRemoveSql.close();
928 } catch (Throwable f) {
929 ;
930 }
931 this.preparedRemoveSql = null;
932
933 try {
934 preparedLoadSql.close();
935 } catch (Throwable f) {
936 ;
937 }
938 this.preparedLoadSql = null;
939
940 // Close this database connection, and log any errors
941 try {
942 dbConnection.close();
943 } catch (SQLException e) {
944 manager.getContainer().getLogger().error(sm.getString(getStoreName() + ".close", e.toString())); // Just log it here
945 } finally {
946 this.dbConnection = null;
947 }
948
949 }
950
951 /**
952 * Release the connection, not needed here since the
953 * connection is not associated with a connection pool.
954 *
955 * @param conn The connection to be released
956 */
957 protected void release(Connection conn) {
958 ;
959 }
960
961 /**
962 * Called once when this Store is first started.
963 */
964 public void start() throws LifecycleException {
965 super.start();
966
967 // Open connection to the database
968 this.dbConnection = getConnection();
969 }
970
971 /**
972 * Gracefully terminate everything associated with our db.
973 * Called once when this Store is stopping.
974 *
975 */
976 public void stop() throws LifecycleException {
977 super.stop();
978
979 // Close and release everything associated with our db.
980 if (dbConnection != null) {
981 try {
982 dbConnection.commit();
983 } catch (SQLException e) {
984 ;
985 }
986 close(dbConnection);
987 }
988 }
989 }