/*
 * The MIT License
 *
 * Copyright (c) 2014 Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.github.olivergondza.dumpling;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Scanner;

import javax.annotation.Nonnull;

public class Util {

    public static final @Nonnull String NL = System.getProperty("line.separator", "\n");

    public static InputStream resource(Class<?> testClass, String resource) {
        InputStream res = testClass.getResourceAsStream(testClass.getSimpleName() + "/" + resource);
        if (res == null) throw new AssertionError("Resource does not exist: " + testClass.getSimpleName() + "/" + resource);
        return res;
    }

    public static InputStream resource(String resource) {
        if (!resource.startsWith("/")) {
            resource = "/" + resource;
        }
        InputStream res = Util.class.getResourceAsStream(resource);
        if (res == null) throw new AssertionError("Resource does not exist: " + resource);
        return res;
    }

    public static File asFile(InputStream is, File file) throws IOException {
        FileWriter fw = new FileWriter(file);
        try {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                fw.append(new String(buffer, 0, length));
            }
        } finally {
            fw.close();
        }

        return file;
    }

    public static File asFile(InputStream is) {
        File file = null;
        try {
            file = File.createTempFile("dumpling", "streamFile");
            file.deleteOnExit();
            return asFile(is, file);
        } catch (IOException ex) {
            if (file != null) {
                file.delete();
            }
            throw new AssertionError(ex);
        }
    }

    public static String asString(InputStream is) {
        StringBuilder sb = new StringBuilder();
        try {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, length));
            }
            return sb.toString();
        } catch (IOException ex) {
            throw new AssertionError(ex);
        }
    }

    public static void pause(int time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException ex) {
        }
    }

    public static String formatTrace(String... frames) {
        StringBuilder sb = new StringBuilder();
        for (String frame: frames) {
            sb.append('\t').append(frame).append(NL);
        }

        return sb.toString();
    }

    public static String multiline(String... lines) {
        StringBuilder sb = new StringBuilder();
        for (String line: lines) {
            sb.append(line).append(NL);
        }

        return sb.toString();
    }

    public static int currentPid() {
        return Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().replaceAll("@.*", ""));
    }

    public static <T> T only(Iterable<T> set) {
        Iterator<T> it = set.iterator();
        T elem = it.next();
        if (elem == null || it.hasNext()) throw new AssertionError(
                "One set element expected: " + set
        );

        return elem;
    }

    public static String currentProcessOut(InputStream os) {
        final StringBuilder out = new StringBuilder();
        try {
            int length = os.available();
            byte[] buffer = new byte[length];
            int read = os.read(buffer, 0, length);
            if (read != -1) { // No out
                out.append(new String(buffer));
            }
        } catch (IOException ex) {
            throw new Error(ex);
        }

        return out.toString();
    }

    public static String fileContents(File file) throws IOException {
        Scanner scanner = null;
        try {
            scanner = new Scanner(file);
            return scanner.useDelimiter("\\A").next();
        } catch (NoSuchElementException ex) {
            return ""; // empty
        } finally {
            if (scanner != null) scanner.close();
        }
    }

    public static Error processTerminatedPrematurely(Process process, int exit, Exception cause) {
        AssertionError error = new AssertionError(
                "Process under test probably terminated prematurely. Exit code: "
                        + exit + "\nSTDOUT: " + currentProcessOut(process.getInputStream())
                        + "\nSTDERR: " + currentProcessOut(process.getErrorStream())
        );
        error.initCause(cause);
        return error;
    }

    public static ProcessBuilder processBuilder() {
        ProcessBuilder pb = new ProcessBuilder();
        try { // Inherit error on JAVA 7 and above
            Class<?> redirect = Class.forName("java.lang.ProcessBuilder.Redirect");
            ProcessBuilder.class.getMethod("redirectError", redirect).invoke(redirect.getField("INHERIT"));
        } catch (ClassNotFoundException e) {
            // Java 6 - less helpful messages
        } catch (NoSuchFieldException e) {
            // Java 6 - less helpful messages
        } catch (IllegalAccessException e) {
            // Java 6 - less helpful messages
        } catch (NoSuchMethodException e) {
            // Java 6 - less helpful messages
        } catch (InvocationTargetException e) {
            // Java 6 - less helpful messages
        }
        return pb;
    }
}

@@ -6120,16 +6120,20 @@
 t error 
+out 
 on JAVA 
@@ -6215,17 +6215,17 @@
 sBuilder
-.
+$
 Redirect
@@ -6244,558 +6244,345 @@
     
-ProcessBuilder.class.getMethod(%22redirectError%22, redirect).invoke(redirect.getField(%22INHERIT%22));%0A        %7D catch (ClassNotFoundException e) %7B%0A            // Java 6 - less helpful messages%0A        %7D catch (NoSuchFieldException e) %7B%0A            // Java 6 - less helpful messages%0A        %7D catch (IllegalAccessException e) %7B%0A            // Java 6 - less helpful messages%0A        %7D catch (NoSuchMethodException e) %7B%0A            // Java 6 - less helpful messages%0A        %7D catch (InvocationTargetException e) %7B%0A            // Java 6 - less helpful messages
+Object inherit = redirect.getDeclaredField(%22INHERIT%22).get(null);%0A            ProcessBuilder.class.getMethod(%22redirectError%22, redirect).invoke(pb, inherit);%0A            return pb;%0A        %7D catch (Throwable e) %7B%0A            System.out.println(%22Java 6 detected - unable to diagnose test process failures%22);%0A            e.printStackTrace();
 %0A   
@@ -6580,32 +6580,33 @@
 ce();%0A        %7D%0A
+%0A
         return p

Fix conditional stderr redirection in tests