/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 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:
//     Oracle - initial API and implementation from Oracle TopLink
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
package org.eclipse.persistence.tools;

import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.Objects;
import java.util.Properties;
import java.util.Vector;

/**
 * This class performs package renaming. It demonstrates the following:
 *
 * a) Reading the properties file to be a reference for changing the package
 * name from your source code.
 *
 * b) Traverse source root directory for creating a corresponding output directory
 * and finding the java source file(s) to be changing the package name.
 *
 * c) Search and replace the old TopLink package name(s) with new one(s) according to the reference.
 *
 * You will be able to see the logging message at the command line window
 * where the PackageRenamer is running.
 *
 */
public class PackageRenamer {
    int numberOfTotalFile = 0;
    int numberOfChangedFile = 0;

    // contains the option of Log file.
    boolean specifyLogFile = false;
    java.io.PrintWriter outLog = null;

    // contains the Log File
    String logFileString = null;
    java.io.File logFile;

    // contains the source-root-directory
    java.io.File sourceRootDirFile;

    // contains the destination-root-directory
    java.io.File destinationRootDir;

    // contains the properties file path
    String sourceProperties;

    // contains a reference for renaming
    Properties properties = null;
    String propertiesFileName;
    boolean VERBOSE = true;
    protected static final String SYSTEM_OUT = "System.out";
    BufferedReader reader = null;
    String[] UNSUPPORTED_EXTENSIONS = { "jar", "zip", "ear", "war", "dll", "class", "exe" };
    int BUFSIZ = 1024 * 4;
    final static String CR;

    static {
        // bug 2756643
        CR = PrivilegedAccessHelper.shouldUsePrivilegedAccess() ?
                AccessController.doPrivileged(new PrivilegedAction<>() {
                    @Override
                    public String run() {
                        return System.getProperty("line.separator");
                    }
                })
                : System.getProperty("line.separator");
    }

    /**
    * The constructor of a PackageRenamer class.
    */
    public PackageRenamer() {
        this(getDefaultPropertiesFileName());
    }

    public PackageRenamer(String propertiesFileName) {
        System.out.println("");
        System.out.println("TopLink Package Renamer");
        System.out.println("-----------------------");
        System.out.println(bannerText());
        sourceRootDirFile = existingDirectoryFromPrompt();
        System.out.println("");
        destinationRootDir = promptForDestinationDirectory();
        System.out.println("");
        this.propertiesFileName = propertiesFileName;
        outLog = streamForNonExistentFilePrompt();
        properties = readChangesFile(propertiesFileName);
    }

    public PackageRenamer(String[] args) {
        this.propertiesFileName = args[0];
        sourceRootDirFile = buildAndCheckExistingDirFile(args[1]);
        destinationRootDir = buildAndCheckDestinationFile(args[2]);
        if (args.length == 4) {
            outLog = buildAndCheckLogWriter(args[3]);
        } else {
            outLog = buildAndCheckLogWriter(SYSTEM_OUT);
        }
        properties = readChangesFile(args[0]);
        logln(bannerText());
    }

    protected String bannerText() {
        StringBuilder stringBuilder = new StringBuilder(CR.length()*3+66+42);
        stringBuilder.append(CR);
        stringBuilder.append("NOTE: The package renamer is meant to be run on plain text files. ");
        stringBuilder.append(CR);
        stringBuilder.append("A rename will NOT be done on binary files.");
        stringBuilder.append(CR);
        return stringBuilder.toString();
    }

    /**
     * Do a binary copy of the file byte buffer by byte buffer.
     *
     * @param inFile
     *            The file to copy
     * @param outFile
     *            The destination file
     * @throws FileNotFoundException
     *             if either of the two files does not exist
     * @throws IOException
     *             if any other IO related error occurs
     */
    public void binaryCopy(File inFile, File outFile) throws FileNotFoundException, IOException {
        byte[] buf = new byte[BUFSIZ];
        try (FileInputStream in = new FileInputStream(inFile);
             FileOutputStream out = new FileOutputStream(outFile)) {
            int nBytesRead;
            while ((nBytesRead = in.read(buf)) != -1) {
                out.write(buf, 0, nBytesRead);
            }
        }
    }

    protected boolean bufferContainsNullChar(byte[] buffer, int bufferLength) {
        for (int i = 0; i < bufferLength; i++) {
            if (buffer[i] == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * INTERNAL Creates a destination directory File object under the path
     * passed, verifying correctness.
     *
     * @param aDirString
     *            The path to the directory File object to create
     * @return The destination directory File object
     */
    public File buildAndCheckDestinationFile(String aDirString) {
        if (aDirString == null) {
            throw new PackageRenamerException("Invalid destination directory entered.");
        }

        File aDirFile = new File(aDirString);

        if (aDirFile.exists()) {
            File[] dirContent = aDirFile.listFiles();
            if (dirContent != null && dirContent.length != 0) {
                throw new PackageRenamerException("Output Directory:" + CR + "  '" + aDirString + "'" + CR + "exists and is not empty.");
            }
        }

        if (!aDirFile.isAbsolute()) {
            throw new PackageRenamerException("A relative destination directory was entered:" + CR + "  '" + aDirString + "'" + CR + "The directory must be absolute.");
        }

        // Check if the destination directory is within the source directory. This would create an infinite loop.
        if (directoryIsSubdirectory(sourceRootDirFile, aDirFile)) {
            throw new PackageRenamerException("Invalid destination directory entered:" + CR + "  '" + aDirString + "'" + CR + "It cannot be a sub-directory of the source directory.");
        }

        return aDirFile;
    }

    public File buildAndCheckExistingDirFile(String aDirString) {
        if (aDirString == null) {
            throw new PackageRenamerException("Invalid source directory entered.");
        }

        File aDirFile = new File(aDirString);

        if (!aDirFile.exists() || !aDirFile.isDirectory()) {
            throw new PackageRenamerException("Input Directory:" + CR + "  '" + aDirString + "'" + CR + "does not exist or is not a directory.");
        }

        if (!aDirFile.isAbsolute()) {
            throw new PackageRenamerException("A relative source directory was entered:" + CR + "  '" + aDirString + "'" + CR + "The directory must be absolute.");
        }

        return aDirFile;
    }

    public PrintWriter buildAndCheckLogWriter(String logFileString) {
        if (logFileString == null) {
            throw new PackageRenamerException("Invalid log file name entered.");
        }

        try {
            if (logFileString.equals(SYSTEM_OUT)) {
                return new PrintWriter(System.out);
            } else {
                File aLogFile = new File(logFileString);

                if (aLogFile.exists()) {
                    throw new PackageRenamerException("Specified log file cannot be created:" + CR + "  '" + logFileString + "'");
                }
                FileWriter writerLog = new FileWriter(logFileString);
                return new java.io.PrintWriter(writerLog);
            }
        } catch (IOException ioException) {
            throw new PackageRenamerException("Unhandled IOException occurred while configuring log file: '" + logFileString + "', " + ioException.getMessage());
        }
    }

    protected void cleanup() {
        //Closing the Log file in case it is being open.
        if (outLog != null) {
            outLog.close();
        }
    }

    /**
     * This method creates an output directory for post-rename file(s).
     *
     * @param aDirectory
     *            The output directory to create
     */
    public void createDestinationDirectory(File aDirectory) {
        if (!aDirectory.exists()) {
            if (!aDirectory.mkdirs()) {
                throw new PackageRenamerException("Error while creating directory:" + CR + "  '" + aDirectory + "'");
            }
        } else {
            throw new PackageRenamerException("Error directory: '" + aDirectory + "' already exists but shouldn't.");
        }
    }

    /**
     * Return true if directory2 is contained within directory1. Both
     * directories must be absolute.
     *
     * @param directory1
     *            The higher level directory
     * @param directory2
     *            The lower level directory
     * @return TRUE if directory2 is a subdirectory of directory1
     */
    public static boolean directoryIsSubdirectory(File directory1, File directory2) {
        //        System.out.println(directory1 + " contains " + directory2);
        if (directory2 == null) {
            return false;
        } else if (directory1.equals(directory2)) {
            return true;
        } else {
            return directoryIsSubdirectory(directory1, directory2.getParentFile());
        }
    }

    public File existingDirectoryFromPrompt() {
        System.out.print("Enter the path of the directory which contains the files to rename:" + CR + "> ");
        String aLine = null;
        try {
            aLine = getReader().readLine();
        } catch (IOException exception) {
            throw new PackageRenamerException("Error while reading the source directory: " + exception.getMessage());
        }
        return buildAndCheckExistingDirFile(aLine);
    }

    public static String getDefaultPropertiesFileName() {

        String currentDirectory = PrivilegedAccessHelper.shouldUsePrivilegedAccess() ?
                AccessController.doPrivileged(new PrivilegedAction<>() {
                    @Override
                    public String run() {
                        return System.getProperty("user.dir");
                    }
                })
                : System.getProperty("user.dir");

        return currentDirectory + File.separator + "packageRename.properties";
    }

    public synchronized BufferedReader getReader() {
        if (reader == null) {
            reader = new BufferedReader(new InputStreamReader(System.in));
        }
        return reader;
    }

    /**
     * Return true if the PackageRenamer should work on the given file
     * extension.
     *
     * @param extension
     *            The file extension to check for being supported
     * @return TRUE if the extension is supported
     */
    public boolean isExtensionSupported(String extension) {
        /* This was cut out because the binary check recognize these files and just copy them byte by byte.
        for (int i=0; i<UNSUPPORTED_EXTENSIONS.length; i++) {
            if ( UNSUPPORTED_EXTENSIONS[i].equalsIgnoreCase(extension)) {
                return false;
            }
        }
        */
        return true;
    }

    /**
     * @param str
     *            The String to log
     */
    public void logln(String str) {
        outLog.println(str);
        outLog.flush();
    }

    /**
     * Main method to run the PackageRenamer
     *
     * @param args
     *            Command line arguments
     */
    public static void main(String[] args) {
        // Check the accuracy of the arguments
        PackageRenamer instance = null;
        try {
            // Creates an instance of an PackageRenamer with some arguments.
            if (args.length == 0) {
                instance = new PackageRenamer();
                instance.run();
            } else if (args.length == 1) {
                instance = new PackageRenamer(args[0]);
                instance.run();
            } else if ((args.length == 3) || (args.length == 4)) {
                instance = new PackageRenamer(args);
                instance.run();
            } else {
                usage();
                System.exit(-1);
            }
        } catch (PackageRenamerException exception) {
            usage();
            System.err.println("**************************************************************************");
            System.err.println("Error during package rename. PACKAGE RENAME FAILED.");
            System.err.println(exception.getMessage());
            System.err.println("**************************************************************************");
            System.exit(-1);
        } catch (Throwable unknowException) {
            System.err.println("Unhandled exception was thrown during rename:");
            unknowException.printStackTrace();
            System.exit(-1);
        }

        instance.logln("");
        instance.logln("PACKAGE RENAME WAS SUCCESSFUL");

        instance.cleanup();

    }

    /**
     * Returns the extension of the given file.
     *
     * @param aFile
     *            The file of which to retrieve the extension
     * @return The file extension or an empty string if none was found.
     */
    public String parseFileExtension(File aFile) {
        int index = aFile.getName().lastIndexOf('.');
        if (index == -1) {
            return "";
        } else {
            return aFile.getName().substring(index + 1);
        }
    }

    /**
     * INTERNAL Prompt from System.in for an empty or non-existent directory to
     * use as the destination directory.
     *
     * @return The destination directory File object
     */
    protected File promptForDestinationDirectory() {
        System.out.print("Enter the path of the directory to which files are to be copied:" + CR + "> ");
        String aLine = null;
        try {
            aLine = getReader().readLine();
        } catch (IOException exception) {
            throw new PackageRenamerException("Error while reading the destination directory specified: " + exception.getMessage());
        }
        return buildAndCheckDestinationFile(aLine);
    }

    /**
     * This readChangesFile() method reads the given properties file to be a
     * reference for renaming TopLink package name.
     *
     * @param filename
     *            The input file to use for the renaming
     * @return The Properties object containing the renaming information
     */
    public Properties readChangesFile(String filename) {
        Properties props = new Properties();
        InputStream in = null;
        try {
            in = new FileInputStream(filename);
            props.load(in);
        } catch (FileNotFoundException fileNotFoundException) {
            throw new PackageRenamerException("Properties file was not found:" + CR + "  '" + filename + "'");
        } catch (IOException ioException) {
            throw new PackageRenamerException("IO error occurred while reading the properties file:'" + filename + "'" + ioException.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    // ignore
                }
            }
        }
        logln("Using properties file: " + filename);
        return props;
    }

    /**
    * This run() method performs,
    * reading the properties file into properties variable to be a reference for changing package name.
    * creating an destination-root-direetory.
    * and, calling traverseSourceDirectory() method.
    */
    public void run() {
        // Start loging.
        logln("LOG MESSAGES FROM packageRenamer");
        logln("" + new Date());
        logln("");
        logln("INPUT: -----------------> " + sourceRootDirFile.toString());
        logln("OUTPUT: ----------------> " + destinationRootDir.toString());
        //        logln("PROPERTIES FILE: -------> "+sourceProperties);
        //        logln("LOG FILE: --------------> "+writerLog);
        logln("");

        // Root output directory.
        logln("Verifying root output directory...");
        if (!(destinationRootDir.exists())) {
            // Create root directory for output first.
            logln("");
            logln("Creating root output directory...");
            createDestinationDirectory(destinationRootDir);
            logln("");
        }
        logln("Verifying root output directory...DONE");
        logln("");

        // Listing the changed file(s)
        logln("List of changed file(s): ");
        logln("");
        traverseSourceDirectory(sourceRootDirFile);
        logln("");
        logln("Total Changed File(s): ------> " + numberOfChangedFile);
        logln("Total File(s):         ------> " + numberOfTotalFile);
        logln("");

    }

    protected PrintWriter streamForNonExistentFilePrompt() {
        System.out.print("Enter the absolute path of the log file [Hit Enter for SYSTEM.OUT]:" + CR + "> ");
        String aLine = null;
        try {
            aLine = getReader().readLine();
        } catch (IOException exception) {
            throw new PackageRenamerException("Error while reading the name of the log file: " + exception.getMessage());
        }
        if ((aLine != null) && (aLine.length() == 0)) {
            return buildAndCheckLogWriter(SYSTEM_OUT);
        } else {
            return buildAndCheckLogWriter(aLine);
        }
    }

    /**
     * This runSearchAndReplacePackageName() reads a pre-rename source file all
     * into string variable and replacing the old package names with the new
     * ones according to the properties file.
     *
     * @param sourceFile
     *            The source file to process
     */
    public void runSearchAndReplacePackageName(java.io.File sourceFile) {
        String stringContainAllFile = "";
        String sourceFileName = sourceFile.toString();
        String sourceFileNameWithoutRoot = sourceFile.toString().substring(sourceRootDirFile.toString().length() + 1);

        // Rename the file name if required.
        sourceFileNameWithoutRoot = returnNewFileNameIfRequired(sourceFileNameWithoutRoot);

        String destinationFileName = destinationRootDir.toString() + File.separator + sourceFileNameWithoutRoot;

        // Reading file into string.
        // stringContainAllFile = readAllStringsFromFile(sourceFileName);
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new java.io.File(sourceFileName));
            byte[] buf = new byte[BUFSIZ];
            StringBuilder strBuf = new StringBuilder((int)new java.io.File(sourceFileName).length());
            int i = 0;
            while ((i = fis.read(buf)) != -1) {
                if (bufferContainsNullChar(buf, i)) {
                    // This is a binary file, just copy it byte by byte to the new location. Do not do any renaming.
                    fis.close();
                    binaryCopy(sourceFile, new File(destinationFileName));
                    return;
                }
                String str = new String(buf, 0, i);
                strBuf.append(str);
            }
            fis.close();
            stringContainAllFile = new String(strBuf);

        } catch (IOException ioException) {
            throw new PackageRenamerException("Unexpected exception was thrown during file manipulation." + ioException.getMessage());
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (Exception e) {
                    // ignore
                }
            }
        }

        // Sorting key package name.
        Vector<Object> aVector = new Vector<>();
        for (Enumeration<Object> e = properties.keys(); e.hasMoreElements();) {
            aVector.addElement(e.nextElement());
        }
        String[] aStringArrayOfSortedKeyPackageName = new String[aVector.size()];
        aVector.copyInto(aStringArrayOfSortedKeyPackageName);
        Arrays.sort(aStringArrayOfSortedKeyPackageName);

        // Starting to rename.
        boolean alreadyPrint = false;
        int index = aStringArrayOfSortedKeyPackageName.length;
        for (Enumeration<Object> enumtr = properties.keys(); enumtr.hasMoreElements();) {
            enumtr.nextElement();
            String key = aStringArrayOfSortedKeyPackageName[index - 1];
            String value = (String)properties.get(key);
            index -= 1;

            // Printing the changed file.
            int found = stringContainAllFile.indexOf(key);
            if ((found != -1) && (!alreadyPrint)) {
                alreadyPrint = true;
                logln((numberOfChangedFile + 1) + ". " + destinationFileName);
                numberOfChangedFile++;
            }

            // replacing the old package name.
            stringContainAllFile = replace(stringContainAllFile, key, value);
        }

        // Writing output file.
        try {
            FileWriter writer = new FileWriter(destinationFileName);
            java.io.PrintWriter out = new java.io.PrintWriter(writer);
            out.print(stringContainAllFile);
            out.close();

        } catch (FileNotFoundException fileNotFoundException) {
            throw new PackageRenamerException("Could not find file to write:" + CR + "  '" + destinationFileName + "'" + CR + fileNotFoundException.getMessage());
        } catch (IOException ioException) {
            throw new PackageRenamerException("Unexpected exception was thrown while writing the file: '" + destinationFileName + "', " + ioException.getMessage());
        }
    }

    /**
     * Do a search and replace in a string.
     *
     * @param str
     *            The original String
     * @param oldChars
     *            The character pattern to replace
     * @param newChars
     *            The character pattern to replace the existing with
     * @return the modified String
     */
    public static String replace(String str, String oldChars, String newChars) {
        int len;
        int pos;
        int lastPos;

        len = newChars.length();
        pos = str.indexOf(oldChars);
        lastPos = pos;

        while (pos > -1) {
            String firstPart;
            String lastPart;

            firstPart = str.substring(0, pos);
            lastPart = str.substring(pos + oldChars.length(), str.length());
            str = firstPart + newChars + lastPart;
            lastPos = pos + len;
            pos = str.indexOf(oldChars, lastPos);
        }

        return (str);
    }

    /**
     * Renames a file based on the properties passed.
     *
     * @param aSourceFileNameWithoutRoot
     *            The original filename
     * @return The new filename, regardless of whether is has been changed
     */
    public String returnNewFileNameIfRequired(String aSourceFileNameWithoutRoot) {
        for (Enumeration<Object> enumtr = properties.keys(); enumtr.hasMoreElements();) {
            String key = (String)enumtr.nextElement();

            if (aSourceFileNameWithoutRoot.indexOf(key) != -1) {
                // replacing the old package name.
                aSourceFileNameWithoutRoot = replace(aSourceFileNameWithoutRoot, key, (String)properties.get(key));
            }
        }

        // just simply return whether it has been changed.
        return aSourceFileNameWithoutRoot;
    }

    /**
     * This traverseSourceDirectory() traverse source-root-directory, creating
     * an corresponding output directory, and calling another method for
     * replacing old TopLink package name.
     *
     * @param aDirectoryString
     *            The source root directory to traverse
     */
    public void traverseSourceDirectory(java.io.File aDirectoryString) {
        Objects.requireNonNull(aDirectoryString);
        java.io.File[] filesAndDirectories = aDirectoryString.listFiles();
        if (filesAndDirectories == null) {
            //no content, nothing to work with
            return;
        }
        for (int i = 0; i < filesAndDirectories.length; i++) {
            java.io.File fileOrDirectory = filesAndDirectories[i];
            if (fileOrDirectory.isDirectory()) {
                String sourceDirectoryName = fileOrDirectory.toString();
                String destinationDirectoryName = destinationRootDir.toString() + sourceDirectoryName.substring(sourceRootDirFile.toString().length(), sourceDirectoryName.length());
                createDestinationDirectory(new java.io.File(destinationDirectoryName));
                traverseSourceDirectory(fileOrDirectory);
            } else {
                // it is a file.
                numberOfTotalFile++;
                // Check that it does not have an unsupported file extension
                String fileExtension = parseFileExtension(fileOrDirectory);
                if (isExtensionSupported(fileExtension)) {
                    runSearchAndReplacePackageName(fileOrDirectory);
                }
            }
        }
    }

    public static void usage() {
        System.out.println("");
        System.out.println("TopLink Package Renamer");
        System.out.println("-----------------------");
        System.out.println("");
        System.out.println("The package  renamer should  be run  once on user source code, configuration");
        System.out.println("files,  and   Mapping  Workbench  project  files  that  have  references  to");
        System.out.println("pre-Oracle 9iAS TopLink 9.0.3  API  packages.  The package renamer  works on");
        System.out.println("plain text files and should NOT be run on binary files such as JAR files.");
        System.out.println("");
        System.out.println("The package renamer supports two command line usages. A call which specifies");
        System.out.println("all the required arguments, and  a  call which takes only one parameter.  In");
        System.out.println("this last case, the user is prompted for the missing arguments.");
        System.out.println("");
        System.out.println("Usage:");
        System.out.println("");
        System.out.println("java org.eclipse.persistence.tools.PackageRenamer <properties-file>");
        System.out.println("");
        System.out.println("OR");
        System.out.println("");
        System.out.println("java org.eclipse.persistence.tools.PackageRenamer <properties-file> <source-root-directory> <destination-root-directory> [ <log-file> ]");
        System.out.println("");
        System.out.println("where:");
        System.out.println("\t<properties-file> - File containing  a list of  old and new package");
        System.out.println("\tnames.");
        System.out.println("");
        System.out.println("\t<source-root-directory> - Absolute path name of the directory which");
        System.out.println("\tcontains all the file to be converted.  The <source-root-directory>");
        System.out.println("\twill be searched recursively for files  to convert.  This directory");
        System.out.println("\tshould contain only the plain text files to be converted.");
        System.out.println("");
        System.out.println("\t<destination-root-directory> - Absolute path name of  the directory");
        System.out.println("\twhere the converted directory  structure will be copied.  All files");
        System.out.println("\twill be copied to  the new directory structure whether changes were");
        System.out.println("\tmade or not. This directory must either not exist or be empty.");
        System.out.println("");
        System.out.println("\t<log-file> - The logging  of  the  renaming process will be written");
        System.out.println("\tto the <log-file>.  If no  <log-file>  is  specified  then  logging");
        System.out.println("\twill be written to standard output.");
        System.out.println("");
    }

    // Made static final for performance reasons.
    public static final class PackageRenamerException extends RuntimeException {
        public PackageRenamerException(String aMessage) {
            super(aMessage);
        }
    }
}
