/*
 * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2017, 2018 IBM Corporation 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:
//     04/24/2017-2.6 Jody Grassel
//       - 515712: ServerSession numberOfNonPooledConnectionsUsed can become invalid when Exception is thrown connecting accessor
package org.eclipse.persistence.connwrapper;

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.
 *
 * NOTE: Copied into eclipselink.jpa.test.jse from /eclipselink.core.test/src/org/eclipse/persistence/testing/framework/DriverWrapper.java
 */
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 RuntimeException("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 RuntimeException("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
     */
    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;
        }
    }

    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;
        }
    }

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

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

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

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

    public Logger getParentLogger() {return null;}
}
