/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2012 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 *  $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.tests.applications.osgi.datasources;

import java.sql.Connection;
import java.sql.Statement;

import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import org.ow2.easybeans.osgi.annotation.OSGiResource;
import org.ow2.jonas.datasource.DataSourceService;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
 * @author Loic Albertin
 */
@Stateless(mappedName = "DataSourceServiceBean")
public class DataSourceServiceBean implements IDataSourceService {
    /**
     * Logger.
     */
    private static Log LOGGER = LogFactory.getLog(DataSourceServiceBean.class);

    /**
     * H2 Driver classname.
     */
    private static final String H2_DS_CLASSNAME = "org.h2.jdbcx.JdbcDataSource";

    @OSGiResource(type = DataSourceService.class)
    private DataSourceService dataSourceService = null;

    public boolean testDefault() throws Exception {
        String jndiName = dataSourceService
                .deployDataSource(H2_DS_CLASSNAME, "", "url", "user", "passwd", "dbName", -1, "serverName", -1, false, -1, -1, -1, -1, -1,
                        0, null);

        Object dataSource = new InitialContext().lookup(jndiName);
        if (dataSource == null) {
            throw new Exception("JNDI lookup returned a null reference");
        }

        if (!DataSource.class.isAssignableFrom(dataSource.getClass())) {
            throw new Exception("data source reference is an instance of " + dataSource.getClass().getName() + " while a " +
                    DataSource.class.getName() + " was expected");
        }
        return true;
    }

    public boolean testDSCache() throws Exception {
        String jndiName1 = dataSourceService
                .deployDataSource(H2_DS_CLASSNAME, "", "url", "user", "passwd", "dbName", -1, "serverName", -1, false, -1, -1, -1,
                        -1, -1,
                        0, null);

        Object dataSource1 = new InitialContext().lookup(jndiName1);
        if (dataSource1 == null) {
            throw new Exception("JNDI lookup returned a null reference");
        }

        if (!DataSource.class.isAssignableFrom(dataSource1.getClass())) {
            throw new Exception("data source reference is an instance of " + dataSource1.getClass().getName() + " while a " +
                    DataSource.class.getName() + " was expected");
        }

        // Call it a second time
        String jndiName2 = dataSourceService
                .deployDataSource(H2_DS_CLASSNAME, "", "url", "user", "passwd", "dbName", -1, "serverName", -1, false, -1, -1, -1,
                        -1, -1,
                        0, null);

        Object dataSource2 = new InitialContext().lookup(jndiName2);
        if (dataSource2 == null) {
            throw new Exception("JNDI lookup returned a null reference");
        }

        if (!DataSource.class.isAssignableFrom(dataSource2.getClass())) {
            throw new Exception("data source reference is an instance of " + dataSource2.getClass().getName() + " while a " +
                    DataSource.class.getName() + " was expected");
        }


        if (dataSource1 != dataSource2) {
            throw new Exception("Caching error two identical calls doesn't return the same object");
        }

        return true;
    }

    public boolean testDSUsage() throws Exception {
        final int isolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
        final boolean transactional = true;
        final int initialPoolSize = 30;
        final int maxPoolSize = 40;
        final int minPoolSize = 50;
        final int maxIdleTime = 600;
        final int maxStatements = 70;
        final int loginTimeout = 800;
        String jndiName = dataSourceService
                .deployDataSource(H2_DS_CLASSNAME, "", "jdbc:h2:mem:testDSUsage", "user", "passwd", "", -1, "localhost", isolationLevel,
                        transactional, initialPoolSize, maxPoolSize, minPoolSize, maxIdleTime, maxStatements, loginTimeout, null);

        Object dataSourceObj = new InitialContext().lookup(jndiName);
        if (dataSourceObj == null) {
            throw new Exception("JNDI lookup returned a null reference");
        }

        if (!DataSource.class.isAssignableFrom(dataSourceObj.getClass())) {
            throw new Exception("data source reference is an instance of " + dataSourceObj.getClass().getName() + " while a " +
                    DataSource.class.getName() + " was expected");
        }

        DataSource dataSource = (DataSource) dataSourceObj;
        Connection connection = dataSource.getConnection();
        Statement statement = null;
        try {
            statement = connection.createStatement();
            // Try to drop table if exists
            String query = "DROP TABLE datasource_service_test";
            try {
                statement.executeUpdate(query);
            } catch (Exception e) {
                // Table may not exist
                LOGGER.debug("Table doesn't exist yet", e);
            }

            query = "create table datasource_service_test " + "(NAME varchar(50), " + "LASTNAME varchar(50))";
            statement = connection.createStatement();
            statement.executeUpdate(query);

            String insertTest = "INSERT INTO datasource_service_test (NAME, LASTNAME) VALUES ('JOHN', 'DOE')";
            statement.executeUpdate(insertTest);
            return true;
        } finally {
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        }

    }

}
