/*
 * 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.jdbcjmsauth.ejb;

import jakarta.ejb.*;
import javax.naming.*;
import javax.sql.*;
import java.rmi.*;
import java.util.*;
import java.sql.*;

public class SimpleBMPBean
    implements EntityBean
{

    protected DataSource ds;
    protected DataSource ds1;
    int id;

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

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

    public boolean test1() {
        //application auth + user/pwd not specified - should fail
	Connection conn = null;
	boolean passed = false;
	try {
	    conn = ds.getConnection();
	} catch (Exception e) {
	    passed = true;
            System.out.println("----------test1------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {
		}    
	    }
	}

	return passed;
    }
    
    public boolean test2() {
        //application auth + user/pwd  specified - should pass
	Connection conn = null;
	boolean passed = true;
	try {
	    conn = ds.getConnection("DBUSER", "DBPASSWORD");
	} catch (Exception e) {
	    passed = false;
            System.out.println("----------test2------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	return passed;
    }

    public boolean test3() {
        //application auth + wrong user/pwd 
	Connection conn = null;
	boolean passed = false;
	try {
	    conn = ds.getConnection("xyz", "xyz" );
	} catch (Exception e) {
	    passed = true;
            System.out.println("----------test3------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	return passed;
    }
    public boolean test4() {
        //application auth + user/pwd  specified - right initiall
	//wrong the second time
	Connection conn = null;
	boolean passed = false;

	try {
	    conn = ds.getConnection("DBUSER", "DBPASSWORD");
	} catch (Exception e) {
            System.out.println("----------test4------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	    return false;
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	try {
	    conn = ds.getConnection("xyz", "xyz" );
	} catch (Exception e) {
            System.out.println("----------test4------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	    passed = true;
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	return passed;
    }


    public boolean test5() {
        //container auth + user/pwd not specified - should pass
	Connection conn = null;
	boolean passed = true;
	try {
	    conn = ds1.getConnection();
	} catch (Exception e) {
            System.out.println("----------test5------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	    passed = false;
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}

	return passed;
    }
    
    public boolean test6() {
        //container auth + user/pwd  specified - should still pass
	Connection conn = null;
	boolean passed = true;
	try {
	    conn = ds.getConnection("DBUSER", "DBPASSWORD");
	} catch (Exception e) {
            System.out.println("----------test6------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	    passed = false;
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	return passed;
    }

    public boolean test7() {
        //container auth + wrong user/pwd should fail
	Connection conn = null;
	boolean passed = false;
	try {
	    conn = ds.getConnection("xyz", "xyz" );
	} catch (Exception e) {
            System.out.println("----------test7------------");
	    e.printStackTrace();
	    System.out.println("---------------------------");
	    passed = true;
	} finally {
	    if ( conn != null ) {
	        try {
	            conn.close();
		} catch( Exception e1) {}    
	    }
	}


	return passed;
    }

    public void ejbLoad() {}
    public void ejbStore() {}
    public void ejbRemove() {}
    public void ejbActivate() {}
    public void ejbPassivate() {}
    public void unsetEntityContext() {}
    public void ejbPostCreate() {}
}
