com.btmatthews.maven.plugins.inmemdb.db.derby.DerbyDatabase.java Source code

Java tutorial

Introduction

Here is the source code for com.btmatthews.maven.plugins.inmemdb.db.derby.DerbyDatabase.java

Source

/*
 * Copyright 2011-2012 Brian Matthews
 *
 * 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 com.btmatthews.maven.plugins.inmemdb.db.derby;

import com.btmatthews.maven.plugins.inmemdb.Loader;
import com.btmatthews.maven.plugins.inmemdb.MessageUtil;
import com.btmatthews.maven.plugins.inmemdb.db.AbstractSQLDatabase;
import com.btmatthews.maven.plugins.inmemdb.ldr.dbunit.DBUnitCSVLoader;
import com.btmatthews.maven.plugins.inmemdb.ldr.dbunit.DBUnitFlatXMLLoader;
import com.btmatthews.maven.plugins.inmemdb.ldr.dbunit.DBUnitXLSLoader;
import com.btmatthews.maven.plugins.inmemdb.ldr.dbunit.DBUnitXMLLoader;
import com.btmatthews.maven.plugins.inmemdb.ldr.sqltool.SQLLoader;
import com.btmatthews.utils.monitor.Logger;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.derby.drda.NetworkServerControl;
import org.apache.derby.iapi.reference.Property;
import org.codehaus.plexus.util.StringUtils;

import javax.sql.DataSource;
import java.io.OutputStream;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * Implements support for in-memory Apache Derby databases.
 *
 * @author <a href="mailto:brian@btmatthews.com">Brian Matthews</a>
 * @version 1.0.0
 */
public final class DerbyDatabase extends AbstractSQLDatabase {

    /**
     * The connection protocol for in-memory H2 databases.
     */
    private static final String PROTOCOL = "derby://localhost:{0,number,#}/memory:";
    /**
     * Default port Derby listens on, can be altered via setting port property
     */
    private static final int DEFAULT_PORT = 1527;
    /**
     * The name of the additional connection parameter which will cause the
     * database to be created.
     */
    private static final String CREATE = "create";
    /**
     * The name of the additional connection parameter which will cause the
     * database to be dropped.
     */
    private static final String DROP = "drop";
    /**
     * The value used with the {@link #CREATE} and {@link #DROP} connection parameters.
     */
    private static final String TRUE = "true";
    /**
     * The JDBC driver class name.
     */
    private static final String DRIVER_CLASS = "org.apache.derby.jdbc.ClientDriver";
    /**
     * The loaders that are supported for loading data or executing scripts.
     */
    private static final Loader[] LOADERS = new Loader[] { new DBUnitXMLLoader(), new DBUnitFlatXMLLoader(),
            new DBUnitCSVLoader(), new DBUnitXLSLoader(), new SQLLoader() };
    /**
     *
     */
    private static final OutputStream DEV_NULL = new OutputStream() {
        public void write(int b) {
        }
    };
    /**
     * The server used to accept connections from other JVMs.
     */
    private NetworkServerControl server;

    /**
     * The default constructor initializes the default database port.
     */
    public DerbyDatabase() {
        super(DEFAULT_PORT);
    }

    /**
     * Get the database connection protocol used for JDBC connections
     *
     * @return Returns protocol
     */
    protected String getUrlProtocol() {
        return MessageFormat.format(PROTOCOL, getPort());
    }

    /**
     * Get the data source that describes the connection to the in-memory Apache
     * Derby database.
     *
     * @param attributes Additional attributes for the data source connection string.
     * @return Returns {@code dataSource} which was initialised by the
     *         constructor.
     */
    @Override
    public DataSource getDataSource() {
        final BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl(getUrl(getAttributes()));
        dataSource.setUsername(getUsername());
        if (StringUtils.isNotEmpty(getPassword())) {
            dataSource.setPassword(getPassword());
        }
        dataSource.setDriverClassName(DRIVER_CLASS);
        return dataSource;
    }

    /**
     * Get the loaders that are supported for loading data or executing scripts.
     *
     * @return Returns {@link #LOADERS}.
     */
    @Override
    public Loader[] getLoaders() {
        return LOADERS;
    }

    /**
     * Start the in-memory Apache Derby database.
     *
     * @param logger Used to report errors and raise exceptions.
     */
    @Override
    public void start(final Logger logger) {

        logger.logInfo("Starting embedded Derby database");

        System.setProperty(Property.ERRORLOG_FIELD_PROPERTY,
                "com.btmatthews.maven.plugins.inmemdb.db.derby.DerbyDatabase.DEV_NULL");

        try {
            server = new NetworkServerControl(InetAddress.getByName("localhost"), getPort());
            server.start(null);
        } catch (final Exception exception) {
            final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
            logger.logError(message, exception);
            return;
        }

        try {
            Class.forName(DRIVER_CLASS).newInstance();
        } catch (final InstantiationException exception) {
            final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
            logger.logError(message, exception);
            return;
        } catch (final IllegalAccessException exception) {
            final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
            logger.logError(message, exception);
            return;
        } catch (final ClassNotFoundException exception) {
            final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
            logger.logError(message, exception);
            return;
        }

        final Map<String, String> attributes = new HashMap<String, String>();
        attributes.put(CREATE, TRUE);
        try {
            final Connection connection = DriverManager.getConnection(getUrl(attributes), getUsername(),
                    getPassword().length() == 0 ? null : getPassword());
            connection.close();
        } catch (final SQLException exception) {
            final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
            logger.logError(message, exception);
            return;
        }

        logger.logInfo("Started embedded Derby database");
    }

    /**
     * Shutdown the in-memory Apache Derby database by opening a connection with
     * <code>drop=true</code>. If successful this will cause a SQL exception
     * with a SQL State of 08006 and a vendor specific error code of 45000.
     *
     * @param logger Used to report errors and raise exceptions.
     */
    @Override
    public void stop(final Logger logger) {

        logger.logInfo("Stopping embedded Derby database");

        if (server != null) {
            final Map<String, String> attributes = new HashMap<String, String>();
            attributes.put(DROP, TRUE);
            try {
                DriverManager.getConnection(getUrl(attributes), getUsername(),
                        getPassword().length() == 0 ? null : getPassword());
            } catch (final SQLException exception) {
                if (exception.getErrorCode() != 45000 || !"08006".equals(exception.getSQLState())) {
                    final String message = MessageUtil.getMessage(ERROR_STARTING_SERVER, getDatabaseName());
                    logger.logError(message, exception);
                    return;
                }
            }
            try {
                server.shutdown();
            } catch (final Exception exception) {
                final String message = MessageUtil.getMessage(ERROR_STOPPING_SERVER, getDatabaseName());
                logger.logError(message, exception);
                return;
            }
        }

        logger.logInfo("Stopped embedded Derby database");
    }

    @Override
    public boolean isStarted(final Logger logger) {
        if (server != null) {
            try {
                server.ping();
                return true;
            } catch (final Exception e) {
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean isStopped(final Logger logger) {
        try {
            server.ping();
            return false;
        } catch (final Exception e) {
            return true;
        }
    }
}