/*
 * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2014, 2017 IBM Corporation. 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,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     11/04/2014 - Rick Curtis
//       - 450010 : Add java se test bucket
//     12/19/2014 - Dalia Abo Sheasha
//       - 454917 : Added a test to use the IDENTITY strategy to generate values
//     02/16/2017 - Jody Grassel
//       - 512255 : Eclipselink JPA/Auditing capablity in EE Environment fails with JNDI name parameter type
//     04/24/2017-2.6 Jody Grassel
//       - 515712: ServerSession numberOfNonPooledConnectionsUsed can become invalid when Exception is thrown connecting accessor
package org.eclipse.persistence.jpa.test.basic;

import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.InitialContext;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.RollbackException;
import javax.sql.DataSource;

import org.eclipse.persistence.config.EntityManagerProperties;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.connwrapper.DriverWrapper;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
import org.eclipse.persistence.jpa.test.basic.model.Dog;
import org.eclipse.persistence.jpa.test.basic.model.Employee;
import org.eclipse.persistence.jpa.test.basic.model.Person;
import org.eclipse.persistence.jpa.test.basic.model.XmlFish;
import org.eclipse.persistence.jpa.test.framework.DDLGen;
import org.eclipse.persistence.jpa.test.framework.Emf;
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
import org.eclipse.persistence.jpa.test.framework.Property;
import org.eclipse.persistence.jpa.test.framework.SQLListener;
import org.eclipse.persistence.sessions.UnitOfWork;
import org.eclipse.persistence.sessions.server.ConnectionPolicy;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EmfRunner.class)
public class TestBasicPersistence {
    @Emf(createTables = DDLGen.DROP_CREATE, classes = { Dog.class, XmlFish.class, Person.class, Employee.class }, 
            properties = {@Property(name = "eclipselink.cache.shared.default", value = "false")}, 
            mappingFiles = { "META-INF/fish-orm.xml" })
    private EntityManagerFactory emf;

    @SQLListener
    List<String> _sql;

    private static final int rmiPort;
    private static final String dsName = "mockDataSource";
    private static final BogusDataSource mockDataSource = new BogusDataSource("tmpDataSourceImp getConnection called");
    private static Registry rmiRegistry = null;
    private static JMXConnectorServer connector = null;

    static {
        int rmiPortVal = 1099;
        
        String rmiPortProp = System.getProperty("rmi.port");
        if (!(rmiPortProp == null || rmiPortProp.isEmpty())) {
            try {
                rmiPortVal = Integer.valueOf(rmiPortProp);
            } catch (NumberFormatException nfe) {
                // Use default value.
            }
        }
            
        rmiPort = rmiPortVal;
    }

    @BeforeClass
    public static void beforeClass() throws Exception {
        rmiRegistry = LocateRegistry.createRegistry(rmiPort);
        
        // Create and Bind Mock Data Source
        rmiRegistry.bind(dsName, mockDataSource);       

        connector = JMXConnectorServerFactory.newJMXConnectorServer(new JMXServiceURL("service:jmx:rmi://localhost:" + rmiPort),
                new HashMap<String, Object>(), ManagementFactory.getPlatformMBeanServer());
    }

    @AfterClass
    public static void afterClass() throws Exception {
        if (rmiRegistry != null) {
            rmiRegistry.unbind(dsName);
        } 

        if (connector != null) {
            connector.stop();
        }
    }

    @Test
    public void activeTransaction() {
        Assert.assertNotNull(emf);
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
    }

    @Test
    public void testNonNullEmf() {
        Assert.assertNotNull(emf);
    }

    @Test
    public void persistTest() {
        if (emf == null)
            return;
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            Person p = new Person();
            Dog d = new Dog("Bingo");
            p.setDog(d);
            d.setOwner(p);

            em.persist(p);
            em.persist(d);

            em.persist(new XmlFish());
            em.getTransaction().commit();
            em.clear();

            Dog foundDog = em.find(Dog.class, d.getId());
            foundDog.getOwner();
            Assert.assertTrue(_sql.size() > 0);
        } finally {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            em.close();
        }
    }

    @Test
    public void identityStrategyTest() {
        if (emf == null)
            return;
        EntityManager em = emf.createEntityManager();
        try {
            em.getTransaction().begin();
            Employee e = new Employee();
            em.persist(e);
            em.getTransaction().commit();
            em.clear();

            Employee foundEmp = em.find(Employee.class, e.getId());
            Assert.assertNotNull(foundEmp);
        } finally {
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            em.close();
        }
    }

    @Test
    public void testNonJTADataSourceOverride() throws Exception {
        if (emf == null)
            return;

        InitialContext ic = new InitialContext();
        Assert.assertNotNull(ic.lookup(dsName));

        EntityManager em = null;
        boolean pass = false;
        Map<String, Object> properties = new HashMap<>();
        properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, dsName);
        properties.put("eclipselink.jdbc.exclusive-connection.mode", "Always");

        try {
            em = emf.createEntityManager(properties);
            em.clear();
            em.find(Dog.class, 1);
        } catch (RuntimeException expected) {
            pass = expected.getMessage().indexOf("tmpDataSourceImp getConnection called") != -1;
            if (!pass) {
                throw expected;
            }
        } finally {
            if (em != null) {
                em.close();
            }
        }
        Assert.assertTrue("Non JTA datasource was not set or accessed as expected through map of properties", pass);
    }

    /*
     * Verify that the number of non pooled connections used is accounted for accurately in regular non-error scenario usage.
     */
    @Test
    public void testNonpooledConnection() throws Exception {
        System.out.println("********************");
        System.out.println("*BEGIN testNonpooledConnection()");
        if (emf == null) 
            return;

        final EntityManagerFactoryImpl emfi = emf.unwrap(EntityManagerFactoryImpl.class);
        Assert.assertNotNull(emfi);

        // Create an em with a unpooled connection policy, idea taken from EntityManagerJUnitTestSuite.testNonPooledConnection()
        final ServerSession ss = emfi.getServerSession();

        // Clone the connection policy and set the pool name to null to emulate using non-pooled connections
        final ConnectionPolicy connectionPolicy = (ConnectionPolicy)ss.getDefaultConnectionPolicy().clone();
        connectionPolicy.setLogin(ss.getLogin());
        connectionPolicy.setPoolName(null);

        final Map<String, Object> properties = new HashMap<>();
        properties.put(EntityManagerProperties.CONNECTION_POLICY, connectionPolicy);

        final int initialNonPooledConnections = ss.getNumberOfNonPooledConnectionsUsed();
        final int maxNonPooledConnections = ss.getMaxNumberOfNonPooledConnections();
        System.out.println("initialNonPooledConnections = " + initialNonPooledConnections);
        System.out.println("maxNonPooledConnections = " + maxNonPooledConnections);
        if (maxNonPooledConnections != -1 && initialNonPooledConnections >= maxNonPooledConnections) {
            Assert.fail("initialNonPooledConnections >= maxNonPooledConnections, other tests may be leaking.");
        }

        EntityManager em = emf.createEntityManager(properties);
        EntityTransaction et = em.getTransaction();

        try {
            et.begin();

            Person p = new Person();
            Dog d = new Dog("Bingo");
            p.setDog(d);
            d.setOwner(p);

            em.persist(p);
            em.persist(d);
            em.persist(new XmlFish());

            em.flush();

            int nonPooledConnectionsAfterFlush = ss.getNumberOfNonPooledConnectionsUsed();
            System.out.println("nonPooledConnectionsAfterFlush = " + nonPooledConnectionsAfterFlush);
            Assert.assertTrue("Test problem: connection should be not pooled", em.unwrap(UnitOfWork.class).getParent().getAccessor().getPool() == null);
            Assert.assertEquals(initialNonPooledConnections + 1, nonPooledConnectionsAfterFlush);

            et.commit();
            em.clear();

            int nonPooledConnectionsAfterCommit = ss.getNumberOfNonPooledConnectionsUsed();
            System.out.println("nonPooledConnectionsAfterCommit = " + nonPooledConnectionsAfterCommit);
            Assert.assertEquals(initialNonPooledConnections, nonPooledConnectionsAfterCommit);

            Dog foundDog = em.find(Dog.class, d.getId());
            foundDog.getOwner();
            Assert.assertTrue(_sql.size() > 0);

            int nonPooledConnectionsAfterFind = ss.getNumberOfNonPooledConnectionsUsed();
            System.out.println("nonPooledConnectionsAfterFind = " + nonPooledConnectionsAfterFind);
            Assert.assertEquals(initialNonPooledConnections, nonPooledConnectionsAfterFind);
        } finally {
            if (et.isActive()) {
                et.rollback();
            }
            em.close();

            System.out.println("*END testNonpooledConnection()");
        }
    }

    @Test
    public void testNonpooledConnectionWithErrorOnAcquireConnection() throws Exception {
        System.out.println("********************");
        System.out.println("*BEGIN testNonpooledConnectionWithErrorOnAcquireConnection()");
        if (emf == null) 
            return;

        final EntityManagerFactoryImpl emfi = emf.unwrap(EntityManagerFactoryImpl.class);
        Assert.assertNotNull(emfi);

        // Create an em with a unpooled connection policy, idea taken from EntityManagerJUnitTestSuite.testNonPooledConnection()
        final ServerSession ss = emfi.getServerSession();

        // Set up the DriverWrapper/ConnectionWrapper so we can emulate database connection failure
        // cache the original driver name and connection string.
        try {
            setupDriverWrapper(ss);

            // Clone the connection policy and set the pool name to null to emulate using non-pooled connections
            final ConnectionPolicy connectionPolicy = (ConnectionPolicy)ss.getDefaultConnectionPolicy().clone();
            connectionPolicy.setLogin(ss.getLogin());
            connectionPolicy.setPoolName(null);

            final Map<String, Object> properties = new HashMap<>();
            properties.put(EntityManagerProperties.CONNECTION_POLICY, connectionPolicy);

            // Validate against initial non-pooled connection count
            final int initialNonPooledConnections = ss.getNumberOfNonPooledConnectionsUsed();
            final int maxNonPooledConnections = ss.getMaxNumberOfNonPooledConnections();
            System.out.println("initialNonPooledConnections = " + initialNonPooledConnections);
            System.out.println("maxNonPooledConnections = " + maxNonPooledConnections);
            if (maxNonPooledConnections != -1 && initialNonPooledConnections >= maxNonPooledConnections) {
                Assert.fail("initialNonPooledConnections >= maxNonPooledConnections, other tests may be leaking.");
            }

            EntityManager em = emf.createEntityManager(properties);
            EntityTransaction et = em.getTransaction();

            try {
                Person p = new Person();
                Dog d = new Dog("Bingo");
                p.setDog(d);
                d.setOwner(p);

                et.begin();
                final int nonPooledConnectionsBeforePersist = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsBeforePersist = " + nonPooledConnectionsBeforePersist);

                em.persist(p);
                em.persist(d);
                em.persist(new XmlFish());

                final int nonPooledConnectionsBeforeFlush = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsBeforeFlush = " + nonPooledConnectionsBeforeFlush);
                try {
                    DriverWrapper.breakNewConnections(); // .breakDriver(); // would be ideal, but results in bug #515961
                    em.flush();
                    Assert.fail("No PersistenceException was thrown.");
                } catch (PersistenceException pe) {
                    // Expected
                } finally {
                    DriverWrapper.repairAll();
                }

                final int nonPooledConnectionsAfterFlush = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsAfterFlush = " + nonPooledConnectionsAfterFlush);
                Assert.assertEquals("nonPooledConnectionsBeforeFlush == nonPooledConnectionsAfterFlush", nonPooledConnectionsBeforeFlush, nonPooledConnectionsAfterFlush);

                try {
                et.rollback();
                } catch (Throwable t) {
                    // Some databases such as mysql may see the Connection as still set to autocommit=true, and
                    // the DriverWrapper was set to make new connections broken, but the real Connection is
                    // still established, but being "Broken" prevents the Connection from being set autocommit=false.
                }

                final int nonPooledConnectionsAfterRollback = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsAfterRollback = " + nonPooledConnectionsAfterRollback);
                Assert.assertTrue("initialNonPooledConnections >= nonPooledConnectionsAfterRollback", initialNonPooledConnections >= nonPooledConnectionsAfterRollback);
            } finally {
                if (et.isActive()) {
                    et.rollback();
                }
                em.close();
            }
        } finally {
            DriverWrapper.repairAll();
            System.out.println("*END testNonpooledConnectionWithErrorOnAcquireConnection()");
        }
    }

    @Test
    public void testNonpooledConnectionWithErrorOnReleaseConnection() throws Exception {
        System.out.println("********************");
        System.out.println("*BEGIN testNonpooledConnectionWithErrorOnReleaseConnection()");
        if (emf == null) 
            return;

        final EntityManagerFactoryImpl emfi = emf.unwrap(EntityManagerFactoryImpl.class);
        Assert.assertNotNull(emfi);

        // Create an em with a unpooled connection policy, idea taken from EntityManagerJUnitTestSuite.testNonPooledConnection()
        final ServerSession ss = emfi.getServerSession();

        // Set up the DriverWrapper/ConnectionWrapper so we can emulate database connection failure
        // cache the original driver name and connection string.
        try {
            setupDriverWrapper(ss);
            DriverWrapper.repairAll();

            // Clone the connection policy and set the pool name to null to emulate using non-pooled connections
            final ConnectionPolicy connectionPolicy = (ConnectionPolicy)ss.getDefaultConnectionPolicy().clone();
            connectionPolicy.setLogin(ss.getLogin());
            connectionPolicy.setPoolName(null);

            final Map<String, Object> properties = new HashMap<>();
            properties.put(EntityManagerProperties.CONNECTION_POLICY, connectionPolicy);

            // Validate against initial non-pooled connection count
            final int initialNonPooledConnections = ss.getNumberOfNonPooledConnectionsUsed();
            final int maxNonPooledConnections = ss.getMaxNumberOfNonPooledConnections();
            System.out.println("initialNonPooledConnections = " + initialNonPooledConnections);
            System.out.println("maxNonPooledConnections = " + maxNonPooledConnections);
            if (maxNonPooledConnections != -1 && initialNonPooledConnections >= maxNonPooledConnections) {
                Assert.fail("initialNonPooledConnections >= maxNonPooledConnections, other tests may be leaking.");
            }

            EntityManager em = emf.createEntityManager(properties);
            EntityTransaction et = em.getTransaction();

            try {
                et.begin();

                Person p = new Person();
                Dog d = new Dog("Bingo");
                p.setDog(d);
                d.setOwner(p);

                em.persist(p);
                em.persist(d);
                em.persist(new XmlFish());

                final int nonPooledConnectionsBeforeFlush = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsBeforeFlush = " + nonPooledConnectionsBeforeFlush);

                em.flush();
                final int nonPooledConnectionsAfterFlush = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsAfterFlush = " + nonPooledConnectionsAfterFlush);
                Assert.assertEquals("nonPooledConnectionsBeforeFlush + 1 == nonPooledConnectionsAfterFlush", nonPooledConnectionsBeforeFlush + 1, nonPooledConnectionsAfterFlush);

                // The non-pooled Connection would be released after the commit.
                DriverWrapper.breakOldConnections();
                try {
                    et.commit();
                    Assert.fail("No RollbackException was thrown.");
                } catch (RollbackException re) {
                    // Expected
                } finally {
                    DriverWrapper.repairAll();
                }

                int nonPooledConnectionsAfterCommit = ss.getNumberOfNonPooledConnectionsUsed();
                System.out.println("nonPooledConnectionsAfterCommit = " + nonPooledConnectionsAfterCommit);
                Assert.assertTrue("initialNonPooledConnections >= nonPooledConnectionsAfterCommit", initialNonPooledConnections >= nonPooledConnectionsAfterCommit);
            } finally {
                DriverWrapper.repairAll();
                if (et.isActive()) {
                    et.rollback();
                }
                em.close();
            }
        } finally {
            DriverWrapper.repairAll();
            System.out.println("*END testNonpooledConnectionWithErrorOnReleaseConnection()");
        }
    }

    private void setupDriverWrapper(ServerSession ss) {
        // Set up the DriverWrapper/ConnectionWrapper so we can emulate database connection failure
        // cache the original driver name and connection string.
        String originalDriverName = ss.getLogin().getDriverClassName();
        String originalConnectionString = ss.getLogin().getConnectionString();

        if (DriverWrapper.class.getName().equals(originalDriverName)) {
            // DriverWrapper is already set up, so just return.
            return;
        }

        // the new driver name and connection string to be used by the test
        String newDriverName = DriverWrapper.class.getName();
        String newConnectionString = DriverWrapper.codeUrl(originalConnectionString);

        // setup the wrapper driver
        DriverWrapper.initialize(originalDriverName);

        ss.logout();
        ss.getLogin().setDriverClassName(newDriverName);
        ss.getLogin().setConnectionHealthValidatedOnError(true);
        ss.getLogin().setConnectionString(newConnectionString);
        ss.login();
    }
    
    /*
     * Taken from org.eclipse.persistence.testing.tests.jpa.validation.ValidationTestSuite
     */
    public static class BogusDataSource implements DataSource, Remote, Serializable {

        private static final long serialVersionUID = 1L;

        private String text = "foo";

        public BogusDataSource(String text){
            super();
            this.text = text;
        }

        @Override
        public Connection getConnection() throws SQLException {
            RuntimeException exception = new RuntimeException(text);
            throw exception;
        }

        @Override
        public Connection getConnection(String username, String password) throws SQLException {
            return getConnection();
        }

        //rest are ignored
        @Override
        public java.io.PrintWriter getLogWriter() throws SQLException {
            return null;
        }

        @Override
        public void setLogWriter(java.io.PrintWriter out) throws SQLException{}
        @Override
        public void setLoginTimeout(int seconds) throws SQLException{}
        @Override
        public int getLoginTimeout() throws SQLException { return 1; }
        @Override
        public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
        @Override
        public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
        @Override
        public Logger getParentLogger() { return null; }
    }

}
