Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.apache.catalina.session;
 
 import static org.jboss.web.CatalinaMessages.MESSAGES;
 
Implementation of the Store interface that stores serialized session objects in a database. Sessions that are saved are still subject to being expired based on inactivity.

Author(s):
Bip Thelin
Version:
$Revision: 515 $, $Date: 2008-03-17 22:02:23 +0100 (Mon, 17 Mar 2008) $
 
 
 public class JDBCStore
         extends StoreBase implements Store {

    
The descriptive information about this implementation.
 
     protected static String info = "JDBCStore/1.0";

    
Context name associated with this Store
 
     private String name = null;

    
Name to register for this Store, used for logging.
 
     protected static String storeName = "JDBCStore";

    
Name to register for the background thread.
 
     protected String threadName = "JDBCStore";

    
The connection username to use when trying to connect to the database.
 
     protected String connectionName = null;


    
The connection URL to use when trying to connect to the database.
 
     protected String connectionPassword = null;

    
Connection string to use when connecting to the DB.
 
     protected String connectionURL = null;

    
The database connection.
 
     private Connection dbConnection = null;

    
Instance of the JDBC Driver class we use as a connection factory.
 
    protected Driver driver = null;

    
Driver to use.
    protected String driverName = null;
    // ------------------------------------------------------------- Table & cols

    
Table to use.
    protected String sessionTable = "tomcat$sessions";

    
Column to use for /Engine/Host/Context name
    protected String sessionAppCol = "app";

    
Id column to use.
    protected String sessionIdCol = "id";

    
Data column to use.
    protected String sessionDataCol = "data";

    
Is Valid column to use.
    protected String sessionValidCol = "valid";

    
Max Inactive column to use.
    protected String sessionMaxInactiveCol = "maxinactive";

    
Last Accessed column to use.
    protected String sessionLastAccessedCol = "lastaccess";
    // ------------------------------------------------------------- SQL Variables

    
Variable to hold the getSize() prepared statement.
    protected PreparedStatement preparedSizeSql = null;

    
Variable to hold the keys() prepared statement.
    protected PreparedStatement preparedKeysSql = null;

    
Variable to hold the save() prepared statement.
    protected PreparedStatement preparedSaveSql = null;

    
Variable to hold the clear() prepared statement.
    protected PreparedStatement preparedClearSql = null;

    
Variable to hold the remove() prepared statement.
    protected PreparedStatement preparedRemoveSql = null;

    
Variable to hold the load() prepared statement.
    protected PreparedStatement preparedLoadSql = null;
    // ------------------------------------------------------------- Properties

    
Return the info for this Store.
    public String getInfo() {
        return ();
    }

    
Return the name for this instance (built from container name)
    public String getName() {
        if ( == null) {
            Container container = .getContainer();
            String contextName = container.getName();
            String hostName = "";
            String engineName = "";
            if (container.getParent() != null) {
                Container host = container.getParent();
                hostName = host.getName();
                if (host.getParent() != null) {
                    engineName = host.getParent().getName();
                }
            }
             = "/" + engineName + "/" + hostName + contextName;
        }
        return ;
    }

    
Return the thread name for this Store.
    public String getThreadName() {
        return ();
    }

    
Return the name for this Store, used for logging.
    public String getStoreName() {
        return ();
    }

    
Set the driver for this Store.

Parameters:
driverName The new driver
    public void setDriverName(String driverName) {
        String oldDriverName = this.;
        this. = driverName;
        .firePropertyChange("driverName",
                oldDriverName,
                this.);
        this. = driverName;
    }

    
Return the driver for this Store.
    public String getDriverName() {
        return (this.);
    }

    
Return the username to use to connect to the database.
    public String getConnectionName() {
        return ;
    }

    
Set the username to use to connect to the database.

Parameters:
connectionName Username
    public void setConnectionName(String connectionName) {
        this. = connectionName;
    }

    
Return the password to use to connect to the database.
    public String getConnectionPassword() {
        return ;
    }

    
Set the password to use to connect to the database.

Parameters:
connectionPassword User password
    public void setConnectionPassword(String connectionPassword) {
        this. = connectionPassword;
    }

    
Set the Connection URL for this Store.

Parameters:
connectionURL The new Connection URL
    public void setConnectionURL(String connectionURL) {
        String oldConnString = this.;
        this. = connectionURL;
        .firePropertyChange("connectionURL",
                oldConnString,
                this.);
    }

    
Return the Connection URL for this Store.
    public String getConnectionURL() {
        return (this.);
    }

    
Set the table for this Store.

Parameters:
sessionTable The new table
    public void setSessionTable(String sessionTable) {
        String oldSessionTable = this.;
        this. = sessionTable;
        .firePropertyChange("sessionTable",
                oldSessionTable,
                this.);
    }

    
Return the table for this Store.
    public String getSessionTable() {
        return (this.);
    }

    
Set the App column for the table.

Parameters:
sessionAppCol the column name
    public void setSessionAppCol(String sessionAppCol) {
        String oldSessionAppCol = this.;
        this. = sessionAppCol;
        .firePropertyChange("sessionAppCol",
                oldSessionAppCol,
                this.);
    }

    
Return the web application name column for the table.
    public String getSessionAppCol() {
        return (this.);
    }

    
Set the Id column for the table.

Parameters:
sessionIdCol the column name
    public void setSessionIdCol(String sessionIdCol) {
        String oldSessionIdCol = this.;
        this. = sessionIdCol;
        .firePropertyChange("sessionIdCol",
                oldSessionIdCol,
                this.);
    }

    
Return the Id column for the table.
    public String getSessionIdCol() {
        return (this.);
    }

    
Set the Data column for the table

Parameters:
sessionDataCol the column name
    public void setSessionDataCol(String sessionDataCol) {
        String oldSessionDataCol = this.;
        this. = sessionDataCol;
        .firePropertyChange("sessionDataCol",
                oldSessionDataCol,
                this.);
    }

    
Return the data column for the table
    public String getSessionDataCol() {
        return (this.);
    }

    
Set the Is Valid column for the table

Parameters:
sessionValidCol The column name
    public void setSessionValidCol(String sessionValidCol) {
        String oldSessionValidCol = this.;
        this. = sessionValidCol;
        .firePropertyChange("sessionValidCol",
                oldSessionValidCol,
                this.);
    }

    
Return the Is Valid column
    public String getSessionValidCol() {
        return (this.);
    }

    
Set the Max Inactive column for the table

Parameters:
sessionMaxInactiveCol The column name
    public void setSessionMaxInactiveCol(String sessionMaxInactiveCol) {
        String oldSessionMaxInactiveCol = this.;
        this. = sessionMaxInactiveCol;
        .firePropertyChange("sessionMaxInactiveCol",
                oldSessionMaxInactiveCol,
                this.);
    }

    
Return the Max Inactive column
    public String getSessionMaxInactiveCol() {
        return (this.);
    }

    
Set the Last Accessed column for the table

Parameters:
sessionLastAccessedCol The column name
    public void setSessionLastAccessedCol(String sessionLastAccessedCol) {
        String oldSessionLastAccessedCol = this.;
        this. = sessionLastAccessedCol;
        .firePropertyChange("sessionLastAccessedCol",
                oldSessionLastAccessedCol,
                this.);
    }

    
Return the Last Accessed column
    public String getSessionLastAccessedCol() {
        return (this.);
    }
    // --------------------------------------------------------- Public Methods

    
Return an array containing the session identifiers of all Sessions currently saved in this Store. If there are no such Sessions, a zero-length array is returned.

Throws:
java.io.IOException if an input/output error occurred
    public String[] keys() throws IOException {
        ResultSet rst = null;
        String keys[] = null;
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return (new String[0]);
                }
                try {
                    if ( == null) {
                        String keysSql = "SELECT " +  + " FROM "
                                +  + " WHERE " + 
                                + " = ?";
                         = _conn.prepareStatement(keysSql);
					}
                    .setString(1, getName());
                    rst = .executeQuery();
                    ArrayList tmpkeys = new ArrayList();
                    if (rst != null) {
                        while (rst.next()) {
                            tmpkeys.add(rst.getString(1));
                        }
                    }
                    keys = (String[]) tmpkeys.toArray(new String[tmpkeys.size()]);
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    keys = new String[0];
                    // Close the connection so that it gets reopened next time
                    if ( != null)
                        close();
                } finally {
                    try {
                        if (rst != null) {
                            rst.close();
                        }
                    } catch (SQLException e) {
                        ;
                    }
                    release(_conn);
                }
                numberOfTries--;
            }
        }
        return (keys);
    }

    
Return an integer containing a count of all Sessions currently saved in this Store. If there are no Sessions, 0 is returned.

Throws:
java.io.IOException if an input/output error occurred
    public int getSize() throws IOException {
        int size = 0;
        ResultSet rst = null;
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return (size);
                }
                try {
                    if ( == null) {
                        String sizeSql = "SELECT COUNT(" + 
                                + ") FROM " +  + " WHERE "
                                +  + " = ?";
                         = _conn.prepareStatement(sizeSql);
					}
                    .setString(1, getName());
                    rst = .executeQuery();
                    if (rst.next()) {
                        size = rst.getInt(1);
                    }
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    if ( != null)
                        close();
                } finally {
                    try {
                        if (rst != null)
                            rst.close();
                    } catch (SQLException e) {
                        ;
                    }
                    release(_conn);
                }
                numberOfTries--;
            }
        }
        return (size);
    }

    
Load the Session associated with the id id. If no such session is found null is returned.

Parameters:
id a value of type String
Returns:
the stored Session
Throws:
java.lang.ClassNotFoundException if an error occurs
java.io.IOException if an input/output error occurred
    public Session load(String id)
            throws ClassNotFoundExceptionIOException {
        ResultSet rst = null;
        StandardSession _session = null;
        Loader loader = null;
        ClassLoader classLoader = null;
        ObjectInputStream ois = null;
        BufferedInputStream bis = null;
        Container container = .getContainer();
 
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return (null);
                }
                try {
                    if ( == null) {
                        String loadSql = "SELECT " +  + ", "
                                +  + " FROM " + 
                                + " WHERE " +  + " = ? AND "
                                +  + " = ?";
                         = _conn.prepareStatement(loadSql);
                    }
                    .setString(1, id);
                    .setString(2, getName());
                    rst = .executeQuery();
                    if (rst.next()) {
                        bis = new BufferedInputStream(rst.getBinaryStream(2));
                        if (container != null) {
                            loader = container.getLoader();
                        }
                        if (loader != null) {
                            classLoader = loader.getClassLoader();
                        }
                        if (classLoader != null) {
                            ois = new CustomObjectInputStream(bis,
                                    classLoader);
                        } else {
                            ois = new ObjectInputStream(bis);
                        }
                        if (.getContainer().getLogger().isDebugEnabled()) {
                            .getContainer().getLogger().debug(.jdbcStoreSessionLoad(id));
                        }
                        _session = (StandardSession.createEmptySession();
                        _session.readObjectData(ois);
                        _session.setManager();
                      } else if (.getContainer().getLogger().isDebugEnabled()) {
                        .getContainer().getLogger().debug(.jdbcStoreIdNotFound());
                    }
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    if ( != null)
                        close();
                } finally {
                    try {
                        if (rst != null) {
                            rst.close();
                        }
                    } catch (SQLException e) {
                        ;
                    }
                    if (ois != null) {
                        try {
                            ois.close();
                        } catch (IOException e) {
                            ;
                        }
                    }
                    release(_conn);
                }
                numberOfTries--;
            }
        }
        return (_session);
    }

    
Remove the Session with the specified session identifier from this Store, if present. If no such Session is present, this method takes no action.

Parameters:
id Session identifier of the Session to be removed
Throws:
java.io.IOException if an input/output error occurs
    public void remove(String idthrows IOException {
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return;
                }
                try {
                    if ( == null) {
                        String removeSql = "DELETE FROM " + 
                                + " WHERE " +  + " = ?  AND "
                                +  + " = ?";
                         = _conn.prepareStatement(removeSql);
                    }
                    .setString(1, id);
                    .setString(2, getName());
                    .execute();
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    if ( != null)
                        close();
                } finally {
                    release(_conn);
                }
                numberOfTries--;
            }
        }
        if (.getContainer().getLogger().isDebugEnabled()) {
        }
    }

    
Remove all of the Sessions in this Store.

Throws:
java.io.IOException if an input/output error occurs
    public void clear() throws IOException {
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return;
                }
                try {
                    if ( == null) {
                        String clearSql = "DELETE FROM " + 
                             + " WHERE " +  + " = ?";
                         = _conn.prepareStatement(clearSql);
                    }
                    .setString(1, getName());
                    .execute();
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    if ( != null)
                        close();
                } finally {
                    release(_conn);
                }
                numberOfTries--;
            }
        }
    }

    
Save a session to the Store.

Parameters:
session the session to be stored
Throws:
java.io.IOException if an input/output error occurs
    public void save(Session sessionthrows IOException {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream bos = null;
        ByteArrayInputStream bis = null;
        InputStream in = null;
        synchronized (this) {
            int numberOfTries = 2;
            while (numberOfTries > 0) {
                Connection _conn = getConnection();
                if (_conn == null) {
                    return;
                }
                // If sessions already exist in DB, remove and insert again.
                // TODO:
                // * Check if ID exists in database and if so use UPDATE.
                remove(session.getIdInternal());
                try {
                    bos = new ByteArrayOutputStream();
                    oos = new ObjectOutputStream(new BufferedOutputStream(bos));
                    ((StandardSessionsession).writeObjectData(oos);
                    oos.close();
                    oos = null;
                    byte[] obs = bos.toByteArray();
                    int size = obs.length;
                    bis = new ByteArrayInputStream(obs, 0, size);
                    in = new BufferedInputStream(bissize);
                    if ( == null) {
                        String saveSql = "INSERT INTO " +  + " ("
                           +  + ", " +  + ", "
                           +  + ", " + 
                           + ", " +  + ", "
                           + 
                           + ") VALUES (?, ?, ?, ?, ?, ?)";
                        = _conn.prepareStatement(saveSql);
					}
                    .setString(1, session.getIdInternal());
                    .setString(2, getName());
                    .setBinaryStream(3, insize);
                    .setString(4, session.isValid() ? "1" : "0");
                    .setInt(5, session.getMaxInactiveInterval());
                    .setLong(6, session.getLastAccessedTime());
                    .execute();
                    // Break out after the finally block
                    numberOfTries = 0;
                } catch (SQLException e) {
                    .getContainer().getLogger().error(.jdbcStoreDatabaseError(), e);
                    if ( != null)
                        close();
                } catch (IOException e) {
                    ;
                } finally {
                    if (oos != null) {
                        oos.close();
                    }
                    if (bis != null) {
                        bis.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                    release(_conn);
                }
                numberOfTries--;
            }
        }
        if (.getContainer().getLogger().isDebugEnabled()) {
        }
    }
    // --------------------------------------------------------- Protected Methods

    
Check the connection associated with this store, if it's null or closed try to reopen it. Returns null if the connection could not be established.

Returns:
Connection if the connection suceeded
    protected Connection getConnection() {
        try {
            if ( == null || .isClosed()) {
                open();
                if ( == null || .isClosed()) {
                    .getContainer().getLogger().info(.jdbcStoreConnectionReopenFailed());
                }
            }
        } catch (SQLException ex) {
        }
        return ;
    }

    
Open (if necessary) and return a database connection for use by this Realm.

Throws:
java.sql.SQLException if a database error occurs
    protected Connection open() throws SQLException {
        // Do nothing if there is a database connection already open
        if ( != null)
            return ();
        // Instantiate our database driver if necessary
        if ( == null) {
            try {
                Class clazz = Class.forName();
                 = (Driverclazz.newInstance();
            } catch (ClassNotFoundException ex) {
            } catch (InstantiationException ex) {
            } catch (IllegalAccessException ex) {
            }
        }
        // Open a new connection
        Properties props = new Properties();
        if ( != null)
            props.put("user");
        if ( != null)
            props.put("password");
         = .connect(props);
        .setAutoCommit(true);
        return ();
    }

    
Close the specified database connection.

Parameters:
dbConnection The connection to be closed
    protected void close(Connection dbConnection) {
        // Do nothing if the database connection is already closed
        if (dbConnection == null)
            return;
        // Close our prepared statements (if any)
        try {
            .close();
        } catch (Throwable f) {
            ;
        }
        this. = null;
        try {
            .close();
        } catch (Throwable f) {
            ;
        }
        this. = null;
        try {
            .close();
        } catch (Throwable f) {
            ;
        }
        this. = null;
        try {
            .close();
        } catch (Throwable f) {
            ;
        }
         
		try {
            .close();
        } catch (Throwable f) {
            ;
        }
        this. = null;
        try {
            .close();
        } catch (Throwable f) {
            ;
        }
        this. = null;
        // Close this database connection, and log any errors
        try {
            dbConnection.close();
        } catch (SQLException e) {
        } finally {
            this. = null;
        }
    }

    
Release the connection, not needed here since the connection is not associated with a connection pool.

Parameters:
conn The connection to be released
    protected void release(Connection conn) {
        ;
    }

    
Called once when this Store is first started.
    public void start() throws LifecycleException {
        super.start();
        // Open connection to the database
        this. = getConnection();
    }

    
Gracefully terminate everything associated with our db. Called once when this Store is stopping.
    public void stop() throws LifecycleException {
        super.stop();
        // Close and release everything associated with our db.
        if ( != null) {
            try {
                .commit();
            } catch (SQLException e) {
                ;
            }
            close();
        }
    }
New to GrepCode? Check out our FAQ X