/*
 * Copyright (c) 1998, 2021 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,
 * 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:
//     ailitchev - Bug 256296: Reconnect fails when session loses connectivity;
//                 Bug 256284: Closing anEMF where the database is unavailable results in deployment exception on redeploy.
package org.eclipse.persistence.testing.framework;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Logger;
/*
 * DriverWrapper works together with ConnectionWrapper.
 * This pair of classes allows to intercept calls to Driver and Connection methods.
 * DriverWrapper can imitate both the db going down (or losing network connection to it),
 * and coming back up (or network connection restored).
 * ConnectionWrapper have the same functionality, but applied to a single connection.
 *
 * There's an example of ConnectionWrapper usage in EntityManagerJUnitTestSuite:
 * testEMCloseAndOpen and testEMFactoryCloseAndOpen.
 *
 * To use DriverWrapper in jpa, initialize DriverWrapper - all methods are static - with the original driver name.
 *
 * Then create EMF, using PersistenceUnit properties, substitute:
 * the original driver class for DriverWrapper (optional) and
 * the original url for "coded" (':' substituted for'*') url (otherwise DriverWrapper would not be called - the original driver would).
 * If created EMF uses DriverWrapper it will print out connection string that looks like "jdbc*oracle*thin*@localhost*1521*orcl".
 *
 * DriverWrapper just passes all the calls to the wrapped driver (the one passed to initialize method):
 * connect method wraps the created connection into ConnectionWrapper and caches them.
 *
 * Unless any of "break" methods called it should function in exactly the same way as original driver, the same for connections, too.
 *
 * But of course real fun is in breaking:
 * breakDriver breaks all the methods (that throw SQLException) of the Driver;
 * brealOldConnections breaks all connections produced so far;
 * breakNewConnections ensures that all newly produced connections are broken.
 *
 * Any method called on broken connection results in SQLException.
 *
 * The simple scenarios used in both EntityManagerJUnitTestSuite tests is imitation of db going down, then coming back:
 * going down: call breakDriver and breakOldConnections (calling breakNewConnections is possible but won't add anything -
 * as long as driver is broken there will be no new connections);
 * coming back: call repairDriver - now new functional new connections could be created, but all old connections are still broken.
 *
 * Also you can also break / repair individual connection.
 * If, say breakOldConnections was performed on DriwerWrapper and repair on ConnectionWrapper the chronologically last call wins.
 * There's no harm in breaking (or repairing) several times in a row.
 *
 * You can pass custom exception string to each break method, otherwise defaults used (the string will be in SQLException, also visible in debugger).
 *
 * Another usage that seems useful: stepping through the code in debugger you can trigger SQLException
 * to be thrown by any Connection method at will
 * be setting broken flag on ConnectionWrapper to true.
 *
 * After the EMF using DriverWrapper is closed, call DriverWrapper.clear() to forget the wrapped driver and clear all the cached ConnectionWrappers.
 */
public class DriverWrapper implements Driver {

    // the wrapped driver name
    static String driverName;
    // the wrapped driver
    static Driver driver;

    // if set to true then methods called on the driver throw exception
    static boolean driverBroken;
    static String driverBrokenExceptionString;
    public static String defaultDriverBrokenExceptionString = "DriverWrapper: driver is broken";

    // if set to true then methods called on the connections already acquired throw exception
    static boolean oldConnectionsBroken;
    static String oldConnectionsBrokenExceptionString;
    public static String defaultOldConnectionsBrokenExceptionString =  "DriverWrapper: old connections are broken";

    // if set to true then methods called on the newly acquired connections will throw exception
    static boolean newConnectionsBroken;
    static String newConnectionsBrokenExceptionString;
    public static String defaultNewConnectionsBrokenExceptionString =  "DriverWrapper: new connections are broken";

    // all created ConnectionWrappers are cached
    static HashSet<ConnectionWrapper> connections = new HashSet();

    // register with DriverManager
    static {
        try {
            DriverManager.registerDriver(new DriverWrapper());
        } catch (SQLException ex) {
            throw new TestProblemException("registerDriver failed for DriverWrapper", ex);
        }
    }

    public static String codeUrl(String url) {
        return url.replace(':', '*');
    }
    public static String decodeUrl(String url) {
        return url.replace('*', ':');
    }
    public static void initialize(String newDriverName) {
        clear();
        driverName = newDriverName;
    }

    public static void breakDriver() {
        breakDriver(defaultDriverBrokenExceptionString);
    }
    public static void breakDriver(String exceptionString) {
        driverBroken = true;
        driverBrokenExceptionString = exceptionString;
    }
    public static void repairDriver() {
        driverBroken = false;
        driverBrokenExceptionString = null;
    }

    public static void breakOldConnections() {
        breakOldConnections(defaultOldConnectionsBrokenExceptionString);
    }
    public static void breakOldConnections(String exceptionString) {
        oldConnectionsBroken = true;
        oldConnectionsBrokenExceptionString = exceptionString;
        Iterator<ConnectionWrapper> it = connections.iterator();
        while(it.hasNext()) {
            it.next().breakConnection(oldConnectionsBrokenExceptionString);
        }
    }
    public static void repairOldConnections() {
        oldConnectionsBroken = false;
        oldConnectionsBrokenExceptionString = null;
        Iterator<ConnectionWrapper> it = connections.iterator();
        while(it.hasNext()) {
            it.next().repairConnection();
        }
    }

    public static void breakNewConnections() {
        breakNewConnections(defaultNewConnectionsBrokenExceptionString);
    }
    public static void breakNewConnections(String exceptionString) {
        newConnectionsBroken = true;
        newConnectionsBrokenExceptionString = exceptionString;
    }
    public static void repairNewConnections() {
        newConnectionsBroken = false;
        newConnectionsBrokenExceptionString = null;
    }

    public static void breakAll() {
        breakDriver();
        breakNewConnections();
        breakOldConnections();
    }

    public static void repairAll() {
        repairDriver();
        repairNewConnections();
        repairOldConnections();
    }

    public static void clear() {
        repairAll();
        Iterator<ConnectionWrapper> it = connections.iterator();
        while(it.hasNext()) {
            try {
                it.next().close();
            } catch (SQLException ex) {
                //ignore
            }
        }
        connections.clear();
        driver = null;
        driverName = null;
    }

    static Driver getDriver() {
        if(driver == null) {
            try {
                driver = (Driver)Class.forName(driverName, true, Thread.currentThread().getContextClassLoader()).newInstance();
            } catch (Exception ex) {
                throw new TestProblemException("DriverWrapper: failed to instantiate " + driverName, ex);
            }
        }
        return driver;
    }

    public static boolean driverBroken() {
        return driverBroken;
    }
    public static String getDriverBrokenExceptionString() {
        return driverBrokenExceptionString;
    }

    public static boolean oldConnectionsBroken() {
        return oldConnectionsBroken;
    }
    public static String getOldConnectionsBrokenExceptionString() {
        return oldConnectionsBrokenExceptionString;
    }

    public static boolean newConnectionsBroken() {
        return newConnectionsBroken;
    }
    public static String getNewConnectionsBrokenExceptionString() {
        return newConnectionsBrokenExceptionString;
    }

    /*
     * The following methods implement Driver interface
     */
    @Override
    public Connection connect(String url, java.util.Properties info) throws SQLException {
        if(driverBroken) {
            throw new SQLException(getDriverBrokenExceptionString());
        }
        String decodedUrl = decodeUrl(url);
        if(driverName != null) {
            Connection internalConn = getDriver().connect(decodedUrl, info);
            if (internalConn == null) {
                // The driver should return "null" if it realizes it is the wrong kind of driver to connect to the given URL.
                return null;
            }
            ConnectionWrapper conn = new ConnectionWrapper(internalConn);
            connections.add(conn);
            return conn;
        } else {
            // non-initialized DriverWrapper should be ignored by DriverManager.
            return null;
        }
    }

    @Override
    public boolean acceptsURL(String url) throws SQLException {
        if(driverName != null) {
            if(driverBroken) {
                throw new SQLException(getDriverBrokenExceptionString());
            }
            String decodedUrl = decodeUrl(url);
            return getDriver().acceptsURL(decodedUrl);
        } else {
            // non-initialized DriverWrapper should be ignored by DriverManager.
            return false;
        }
    }

    @Override
    public DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info) throws SQLException {
        if(driverBroken) {
            throw new SQLException(getDriverBrokenExceptionString());
        }
        return getDriver().getPropertyInfo(url, info);
    }

    @Override
    public int getMajorVersion() {
        return getDriver().getMajorVersion();
    }

    @Override
    public int getMinorVersion() {
        return getDriver().getMinorVersion();
    }

    @Override
    public boolean jdbcCompliant() {
        return getDriver().jdbcCompliant();
    }

    @Override
    public Logger getParentLogger() {return null;}
}
