/*

   Derby - Class SetDerbyVersion

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.util.ArrayList;
import java.util.List;

/**
 * Checks the current Derby jars in the source tree directory, obtains the
 * Derby version from them, and replaces the value of the placeholder
 * version tags in the POM files.
 * <p>
 * After this method has been successfully run you should be ready to
 * generate the Maven 2 artifacts for Derby.
 * <p>
 * The main task of this class is to replace the version tags in the Maven
 * POM files. The can be done manually, but exact process would vary from
 * platform to platform. Also, running a search-and-replace could potentially
 * replace tags not supposed to be replaced. To make the Maven 2 artifact
 * publish process simpler, this class was written.
 */
//@NotThreadSafe
public class SetDerbyVersion {

    private static final String PROMPT_CONT_WARN =
            "Do you want to continue despite the warnings?";
    private static final String PROMPT_USE_SANE =
            "Do you want to generate artifacts with SANE jars?";
    private static final String JDBC_URL =
            "jdbc:derby:memory:testDB;create=true";
    private static final String REL_JAR_PATH = "../jars";
    private static final File SANE = new File(REL_JAR_PATH, "sane");
    private static final File INSANE = new File(REL_JAR_PATH, "insane");
    /** List of required jar files the Maven 2 Derby artifacts. */
    private static final String[] JARS = new String[] {
        "derby.jar",
        "derby.war",
        "derbynet.jar",
        "derbyclient.jar",
        "derbytools.jar",
        "derbyoptionaltools.jar",
        // Ignore derbyTesting.jar, not part of the Maven 2 artifacts.
        // "derbyTesting.jar",
        // Ignore derbyrun.jar, not part of the Maven 2 artifacts.
        //"derbyrun.jar",
        // The various locale files.
        "derbyLocale_cs.jar",
        "derbyLocale_de_DE.jar",
        "derbyLocale_es.jar",
        "derbyLocale_fr.jar",
        "derbyLocale_hu.jar",
        "derbyLocale_it.jar",
        "derbyLocale_ja_JP.jar",
        "derbyLocale_ko_KR.jar",
        "derbyLocale_pl.jar",
        "derbyLocale_pt_BR.jar",
        "derbyLocale_ru.jar",
        "derbyLocale_zh_CN.jar",
        "derbyLocale_zh_TW.jar",
    };

    /**
     * Displays a prompt and obtains a yes / no answer from standard in.
     *
     * @param prompt the prompt to display
     * @return {@code true} if the answer is yes, {@code false} if the answer
     *      is no.
     * @throws IOException if reading from standard in fails
     */
    private static boolean getYesNoInput(String prompt)
            throws IOException {
        // We don't care about keeping the objects around, this method will
        // only be used a few times.
        BufferedReader bIn = new BufferedReader(
                new InputStreamReader(System.in));
        while (true) {
            System.out.print(">> " + prompt + " (yes/no) ");
            String answer = bIn.readLine();
            if (answer == null) {
                // We don't know what do to here, so just fail.
                throw new EOFException("Input stream closed.");
            }
            if (answer.equals("yes")) {
                return true;
            } else if (answer.equals("no")) {
                return false;
            }
        }
    }

    /**
     * Set to {@code true} if a warning message is printed. Must be manually
     * reset if used to check for warnings in a part of the code.
     */
    private boolean warnings = false;
    /** The version string inserted into the POMs. */
    private String versionString = "ALPHA_VERSION";
    private File PREFIX;

    /**
     * Prints a warning message and sets the internal warning flag.
     *
     * @param msg the message to print
     */
    private void warn(String msg) {
        warnings = true;
        System.out.println("WARNING! " + msg);
    }

    private void info(String msg) {
        System.out.println(msg);
    }

    /**
     * Checks that all required jars are found in the jar directory.
     *
     * @return {@code true} if all required jars exist, {@code false} otherwise.
     */
    public boolean checkJars()
            throws Exception {
        if (!SANE.exists() && !INSANE.exists()) {
            warn("No jars exist. Produce a Derby release build.");
            return false;
        }
        if (SANE.exists() && INSANE.exists()) {
            warn("Both SANE and INSANE jars exist.");
            return false;
        }
        PREFIX = SANE.exists() ? SANE : INSANE;
        if (SANE.exists()) {
            warn("Only SANE jars exist. Normally INSANE jars are used for a " +
                    "release.");
            boolean answer = getYesNoInput(PROMPT_USE_SANE);
            if (!answer) {
                return false;
            }
        }
        URL[] URLS = new URL[JARS.length];
        for (int i=0; i < JARS.length; i++) {
            URLS[i] = new File(PREFIX, JARS[i]).toURI().toURL();
        }

        warnings = false; // Reuse the warnings flag.
        // Make sure the files are there.
        for (URL url : URLS) {
            File f = new File(url.toURI());
            info(String.format(
                    "Checking file: %-30s %,12d bytes",
                    f.getName(), f.length()));
            if (!f.exists()) {
                warn("Missing file: " + f.getCanonicalPath());
            } else if (f.length() == 0) {
                warn("Empty file: " + f.getCanonicalPath());
            }
        }
        info("");
        if (warnings) {
            // Fail here.
            warn("There are missing or empty jar files.");
            return false;
        }

        // The class loader used for the Derby jars.
        URLClassLoader cl = new URLClassLoader(URLS, null);

        // Extra sanity check for the sanity...
        try {
            Class.forName(
                    "org.apache.derby.shared.common.sanity.SanityManager",
                    true ,cl);
            if (PREFIX == INSANE) {
                warn("Found SanityManager in INSANE build. Aborting.");
                return false;
            }
        } catch (ClassNotFoundException cnfe) {
            if (PREFIX == SANE) {
                warn("Unable to load SanityManager in SANE build. Aborting.");
                return false;
            }
        }

        // Fire up Derby to get the version string.
        Class driverClass =
                Class.forName("org.apache.derby.jdbc.EmbeddedDriver", true, cl);
        Driver driver = (Driver)driverClass.newInstance();
        Connection con = driver.connect(JDBC_URL, null);
        DatabaseMetaData meta = con.getMetaData();
        con.close();
        // Delete the derby.log file.
        new File("derby.log").delete();

        // I.e.: 10.6.0.0 alpha - (882129M)
        String fullVersion = meta.getDatabaseProductVersion();
        String[] components = fullVersion.split(" - ");
        versionString = components[0].replaceAll(" ", "_");
        String srcRevision = components[1].replaceAll("\\(|\\)", "");
        info("Obtained product version string: " + fullVersion);
        info("(version=" + versionString + ", revision=" + srcRevision + ")");
        if (versionString.contains("beta")) {
            warn("This is a BETA build.");
        }
        if (versionString.contains("alpha")) {
            warn("This is an ALPHA build.");
        }
        if (srcRevision.endsWith("M")) {
            warn("The sources had been modified when the jars were built.");
            warnings = true;
        }
        if (warnings) {
            if (!getYesNoInput(PROMPT_CONT_WARN)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Replaces the relevant version tags in the various POM files.
     *
     * @throws IOException if accessing a POM file fails
     */
    public boolean setPOMVersionTags()
            throws IOException {
        File curDir = new File(".");
        boolean gotWarnings = false;
        // We only descend one level, no need for a recursive method.
        for (File topLevel : curDir.listFiles()) {
            if (topLevel.getName().equals("pom.xml")) {
                gotWarnings |= setVersionTag(topLevel);
            }
            if (topLevel.isDirectory()) {
                for (File l1 : topLevel.listFiles()) {
                    if (l1.getName().equals("pom.xml")) {
                        gotWarnings |= setVersionTag(l1);
                        // There is only one POM in each sub-directory.
                        break;
                    }
                }
            }
        }

        // See if we ran into problems when replacing the version tags.
        info("");
        if (gotWarnings) {
            warn("There were errors replacing the POM version tags.");
        } else {
            info("POM version tags replacement succeeded.");
            info("It is recommended that you verify the POM diffs " +
                    "before running Maven.");
        }
        return (warnings == false);
    }

    public void printSanityNote()
            throws IOException {
        if (PREFIX == SANE) {
            info("");
            info("NOTE: Remember to change the <sanity> tag in the top-level");
            info("      POM, setting it to 'sane'.");
        }
    }

    /**
     * Verifies that the correct number of tags were replaced in the POM.
     *
     * @param replaceCount the number of tags replaced
     * @param pom the POM modified
     * @return {@code 0} if the check passed, a negative value if too few tags
     *      were replaced, and a positive value if too many tags were replaced.
     */
    private int checkResult(int replaceCount, File pom) {
        // The locales requires two replacements, due to the dependency.
        String parent = pom.getParent();
        if (parent.contains("derbyLocale")) {
            return (replaceCount - 2);
        // derbynet also requries two replacements (derby.jar dependency)
        } else if (parent.contains("net")) {
            return (replaceCount - 2);
        } else {
            return (replaceCount - 1);
        }
    }

    /**
     * Replaces all qualifying version tags in the specified POM.
     *
     * @param pom the POM to modify
     * @return {@code false} if warnings were produced when replacing,
     *      {@code true} if all seemed to go well.
     *
     * @throws IOException if reading or writing to the POM file fails
     */
    private boolean setVersionTag(File pom)
            throws IOException {
        // Clear internal warning flag.
        warnings = false;
        // Just read the whole file into memory.
        List<String> lines = readFile(pom);

        // Start writing the file back out, and search for tags to replace.
        BufferedWriter bOut = new BufferedWriter(new FileWriter(pom, false));
        int replaced = 0;
        boolean artifactIdOk = false;
        boolean groupIdOk = false;
        // Could have used XML, but keep it simple.
        // artifactId and groupId are used to qualify the version tag, as it can
        // be used in more places than those we want to replace.
        for (String line : lines) {
            // Look for tags for qualification.
            if (line.trim().startsWith("<artifactId>") &&
                    line.contains("derby")) {
                artifactIdOk = true;
            } else if (line.trim().startsWith("<groupId>") &&
                    line.contains("org.apache.derby")) {
                groupIdOk = true;
            }

            // Change line if a qualified version tag, echo otherwise.
            if (line.trim().startsWith("<version>") &&
                    artifactIdOk && groupIdOk) {
                // Replace tag.
                int whitespaceTag = line.indexOf(">");
                bOut.write(line.substring(0, whitespaceTag +1));
                bOut.write(versionString);
                int tagEnd = line.indexOf("<", whitespaceTag);
                bOut.write(line.substring(tagEnd));
                bOut.newLine();
                replaced++;
                artifactIdOk = groupIdOk = false;
            } else {
                bOut.write(line);
                bOut.newLine();
            }
        }
        try {
            bOut.flush();
            bOut.close();
        } catch (IOException ioe) {
            warn("Flushing/closing stream for " + pom.getCanonicalPath() +
                    " failed: " + ioe.getMessage());
        }
        int result = checkResult(replaced, pom);
        if (result == 0) {
            info("Replaced " + replaced + " version tag(s) in " +
                    pom.getParentFile().getName() + "/" + pom.getName());
        } else if (result > 0) {
            warn("Too many version tags (" + replaced + " > " +
                    (replaced - result) + ") replaced in " + pom.getPath());
        } else {
            warn("Too few version tags (" + replaced + " < " +
                    (replaced - result) + ") replaced in " + pom.getPath());
        }
        return warnings;
    }

    /**
     * Reads the contents of a text file.
     *
     * @param f the file to read
     * @return A list containing the lines of the file.
     * @throws IOException if reading the file fails
     */
    private List<String> readFile(File f)
            throws IOException {
        ArrayList<String> lines = new ArrayList<String>();
        BufferedReader bIn = new BufferedReader(new FileReader(f));
        String lineIn;
        try {
            while ((lineIn = bIn.readLine()) != null) {
                lines.add(lineIn);
            }
        } finally {
            try {
                bIn.close();
            } catch (IOException ioe) {
                // Just print a warning.
                warn("Failed to close input stream for " + f.getPath() + ": " +
                        ioe.getMessage());
            }
        }
        return lines;
    }

    /**
     * Quits the JVM if a failure is detected.
     *
     * @param success the return value to check
     */
    private static void ensureSuccess(boolean success) {
        if (!success) {
            System.out.println();
            System.out.println(
                    "!! The process failed or was aborted by the user.");
            System.out.println(
                    "   Read the above output and take corrective measures.");
            System.exit(1);
        }
    }

    /**
     * Checks the current Derby jars in the source tree directory, obtains the
     * Derby version from them, and replaces the value of the placeholder
     * version tags in the POM files.
     * <p>
     * After this method has been successfully run you should be ready to
     * generate the Maven 2 artifacts for Derby.
     *
     * @param args ignored
     * @throws Exception if something goes wrong
     */
    public static void main(String[] args)
            throws Exception {
        SetDerbyVersion sdv = new SetDerbyVersion();
        ensureSuccess(sdv.checkJars());
        ensureSuccess(sdv.setPOMVersionTags());
        sdv.printSanityNote();
    }
}
