/*
 * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.s1asdev.jdbc.datasource40.ejb;

import jakarta.ejb.*;
import javax.naming.*;
import javax.sql.*;
import java.sql.*;
import java.lang.reflect.*;

import com.sun.enterprise.connectors.ConnectorRuntime;

public class SimpleBMPBean
        implements EntityBean {

    protected DataSource ds;
    protected DataSource cpds;
    protected DataSource xads;

    public void setEntityContext(EntityContext entityContext) {
        Context context = null;
        try {
            context = new InitialContext();
            ds = (DataSource) context.lookup("java:comp/env/DSDataSource");
        } catch (NamingException e) {
            throw new EJBException("cant find DS datasource");
        }


        try {
            cpds = (DataSource) context.lookup("java:comp/env/CPDataSource");
        } catch (NamingException e) {
            throw new EJBException("cant find CP datasource");
        }

        try {
            xads = (DataSource) context.lookup("java:comp/env/XADataSource");
        } catch (NamingException e) {
            throw new EJBException("cant find XA datasource");
        }
        System.out.println("[**SimpleBMPBean**] Done with setEntityContext....");
    }

    public Integer ejbCreate() throws CreateException {
        return new Integer(1);
    }

    /**
     * Verify whether the datasource obtained has "unwrap" method <br>
     *
     * @return
     */
    public boolean test1() {
        boolean passed = false;
        try {
            Class dataSourceClass = ds.getClass();
            Method[] methods = dataSourceClass.getMethods();
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].getName().equalsIgnoreCase("unwrap")) {
                    passed = true;
                    System.out.println("Found unwrap() in DataSource class");
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            passed = false;
        }

        return passed;
    }

    /**
     * verify whether the unwrap() on connection's close actually closes appserver's wrapper connection<br>
     *
     * @return
     */
    public boolean test2() {
        Connection conn = null;
        boolean passed = false;
        try {
            conn = ds.getConnection();
            String physicalConnection1 = (((com.sun.appserv.jdbc.DataSource) ds).getConnection(conn)).toString();
            Connection proxyConnection = conn.unwrap(java.sql.Connection.class);
            System.out.println("Proxy Connection : AutoCommit  : " + proxyConnection.getAutoCommit());
            //closing the proxy connection must close "conn" and return it to pool.
            //since there is only one connection in pool, second getConnection will fail if proxyConnection's close
            //did not close the logical connection of pool.
            proxyConnection.close();


            conn = ds.getConnection();
            String physicalConnection2 = (((com.sun.appserv.jdbc.DataSource) ds).getConnection(conn)).toString();

            //Ensure that both the connections are the same.
 		System.out.println("PhysicalConn 1 : " + physicalConnection1);
                System.out.println("PhysicalConn 2 : " + physicalConnection1);

            if (physicalConnection2.equals(physicalConnection1)) {
                passed = true;
		System.out.println("Physical Connections are equal");
            }else{
		System.out.println("Physical Connections are not equal");
	    }
	    

        } catch (Exception e) {
            e.printStackTrace();
            passed = false;
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (Exception e) {
                }
            }
        }
        return passed;
    }

    /**
     * Check whether the datasource.unwrap() works fine<br>
     * For respective resource-type, appropriate driver datasource need to be returned<br>
     *
     * @return
     */
    public boolean test3() {
        Connection conn = null;
        boolean passed = false;
        boolean dstest = false;
        boolean cptest = false;
        boolean xatest = false;

        try {
            Object nativeds = ds.unwrap(javax.sql.DataSource.class);

            if (nativeds instanceof javax.sql.DataSource) {
                dstest = true;
            } else {
                System.out.println("DS did not return object of type javax.sql.DataSource");
                dstest = false;
            }

            Object nativecpds = cpds.unwrap(javax.sql.ConnectionPoolDataSource.class);
            if (nativecpds instanceof javax.sql.ConnectionPoolDataSource) {
                cptest = true;
            } else {
                System.out.println("CP DS did not return object of type javax.sql.ConnectionPoolDataSource");
                cptest = false;
            }
            Object nativexads = xads.unwrap(javax.sql.XADataSource.class);
            if (nativexads instanceof javax.sql.XADataSource) {
                xatest = true;
            } else {
                System.out.println("XA DS did not return object of type javax.sql.XADataSource");
                xatest = false;
            }

            if (dstest && cptest && xatest) {
                passed = true;
                System.out.println("DataSource unwrap() returns appropriate db-datasources");
            }else{
                System.out.println("DataSource unwrap() did not return appropriate db-datasources");
            }

                
        } catch (Exception e) {
            e.printStackTrace();
            passed = false;
        }

        return passed;
    }


    public void ejbLoad() {
    }

    public void ejbStore() {
    }

    public void ejbRemove() {
    }

    public void ejbActivate() {
    }

    public void ejbPassivate() {
    }

    public void unsetEntityContext() {
    }

    public void ejbPostCreate() {
    }
}
