/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed 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.bodington.sqldatabase;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.bodington.database.ConnectionPoolException;
import org.bodington.pool.ObjectPoolException;

/**
 * Class to be used when using an in process HSQLDB connection.
 * This is so that we can load the database from within the context
 * and also so that we shut it down correctly after finishing.
 * @author buckett
 */
public class EmbeddedHSqlDatabase extends SqlDatabase
{
    private static final String HSQLDB_JDBC_DRIVER = "org.hsqldb.jdbcDriver";
    private static Logger log = Logger.getLogger(EmbeddedHSqlDatabase.class);

    /**
     * @throws Exception
     */
    public EmbeddedHSqlDatabase() throws Exception
    {
        super();
    }
    
    /**
     * Allows HSQLDB JDBC urls to include a webapp section.
     * The webapp URLs are mapped across to file URLs inside the WEB-INF
     * folder of the webapp. This depends on having the property 
     * <code>buildingservlet.context.root</code> defined.
     * @param props The BuildingServer properties that are passed across.
     */
    public void init(Properties props) throws Exception
    {
        String contextRoot = props.getProperty("buildingservlet.context.root");
        
        String driver = props.getProperty("sqldatabase.driver", HSQLDB_JDBC_DRIVER);
        String url = props.getProperty("sqldatabase.url", "jdbc:hsqldb:webapp:/database/quickstart");
        String username = props.getProperty("sqldatabase.username", "sa");
        String password = props.getProperty("sqldatabase.password", "");
        
        if (!driver.equals(HSQLDB_JDBC_DRIVER))
            log.warn("You are using the Embedded HSQLDB driver but "
                + "your property 'sqldatabase.driver' isn't set to: "
                + HSQLDB_JDBC_DRIVER);

        url = addContextIfWebApp(url, contextRoot);
        props.setProperty("sqldatabase.driver", driver);
        props.setProperty("sqldatabase.url", url);
        props.setProperty("sqldatabase.username", username);
        props.setProperty("sqldatabase.password", password);
        log.info("Using HSQLDB URL: "+ url);

        super.init(props);
    }
    
    /**
     * Attempts to destroy the database connections.
     * We need a custom HSQLDB version for this so that when a servlet context is
     * reloaded the old database gets shutdown so the new one can be started up.
     * This is because each upon context reload a new classloader is created.
     */
    public void destroy()
    {
        try
        {
            Connection connection = (Connection)connection_pool.getConnection(this);
            Statement statement = connection.createStatement();
            statement.execute("SHUTDOWN");
        }
        catch (ConnectionPoolException ope)
        {
            log.error("Could not get connection from pool. Database might not have been shutdown.");
        }
        catch (SQLException sqle)
        {
            log.error("Error sending the SHUTDOWN command to the database.");
        }
        super.destroy();
    }
    
    /**
     * Attempt to change our special webapp HSQLDB URLs to file ones.
     * @param url The database URL.
     * @param context The servlet context in which we are running.
     * @return The changed JDBC URL.
     */
    private String addContextIfWebApp(String url, String context)
    {
        if (url.startsWith("jdbc:hsqldb:webapp:"))
        {
            return "jdbc:hsqldb:file:" + context + "/WEB-INF/"
                + url.substring("jdbc:hsqldb:webapp:".length());
        }
        return url;
    }

}
