langtools/test/tools/lib/ToolBox.java
author jjg
Wed, 05 Nov 2014 19:48:42 -0800
changeset 27389 301be76491af
parent 27385 fb4a5f118316
child 27547 d07b3dcbc707
permissions -rw-r--r--
8063074: test/tools/javac/plugin/showType/Test.java fails on Windows Reviewed-by: ksrini
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
26100
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     1
/*
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     2
 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     4
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     7
 * published by the Free Software Foundation.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     8
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    13
 * accompanied this code).
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    14
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    18
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    21
 * questions.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    22
 */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    23
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    24
import java.io.BufferedReader;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    25
import java.io.BufferedWriter;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    26
import java.io.ByteArrayInputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    27
import java.io.ByteArrayOutputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    28
import java.io.File;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    29
import java.io.FilterOutputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    30
import java.io.FilterWriter;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    31
import java.io.IOException;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    32
import java.io.InputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    33
import java.io.InputStreamReader;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    34
import java.io.OutputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    35
import java.io.PrintStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    36
import java.io.PrintWriter;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    37
import java.io.StringWriter;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    38
import java.io.Writer;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    39
import java.net.URI;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    40
import java.nio.charset.Charset;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    41
import java.nio.file.FileVisitResult;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    42
import java.nio.file.Files;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    43
import java.nio.file.Path;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    44
import java.nio.file.Paths;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    45
import java.nio.file.SimpleFileVisitor;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    46
import java.nio.file.StandardCopyOption;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    47
import java.nio.file.attribute.BasicFileAttributes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    48
import java.util.ArrayList;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    49
import java.util.Arrays;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    50
import java.util.Collections;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    51
import java.util.EnumMap;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    52
import java.util.HashMap;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    53
import java.util.List;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    54
import java.util.ListIterator;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    55
import java.util.Locale;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    56
import java.util.Map;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    57
import java.util.Objects;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    58
import java.util.jar.Attributes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    59
import java.util.jar.JarEntry;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    60
import java.util.jar.JarOutputStream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    61
import java.util.jar.Manifest;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    62
import java.util.regex.Matcher;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    63
import java.util.regex.Pattern;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    64
import java.util.stream.Collectors;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    65
import java.util.stream.Stream;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    66
import java.util.stream.StreamSupport;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    67
import javax.tools.FileObject;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    68
import javax.tools.ForwardingJavaFileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    69
import javax.tools.JavaCompiler;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    70
import javax.tools.JavaFileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    71
import javax.tools.JavaFileObject;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    72
import javax.tools.SimpleJavaFileObject;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    73
import javax.tools.StandardJavaFileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    74
import javax.tools.StandardLocation;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    75
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    76
import com.sun.tools.javac.api.JavacTaskImpl;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    77
import com.sun.tools.javac.api.JavacTool;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    78
import java.io.IOError;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    79
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    80
/**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    81
 * Utility methods and classes for writing jtreg tests for
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    82
 * javac, javah, javap, and sjavac. (For javadoc support,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    83
 * see JavadocTester.)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    84
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    85
 * <p>There is support for common file operations similar to
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    86
 * shell commands like cat, cp, diff, mv, rm, grep.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    87
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    88
 * <p>There is also support for invoking various tools, like
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    89
 * javac, javah, javap, jar, java and other JDK tools.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    90
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    91
 * <p><em>File separators</em>: for convenience, many operations accept strings
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    92
 * to represent filenames. On all platforms on which JDK is supported,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    93
 * "/" is a legal filename component separator. In particular, even
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    94
 * on Windows, where the official file separator is "\", "/" is a legal
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    95
 * alternative. It is therefore recommended that any client code using
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    96
 * strings to specify filenames should use "/".
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    97
 *
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    98
 * @author Vicente Romero (original)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
    99
 * @author Jonathan Gibbons (revised)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   100
 */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   101
public class ToolBox {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   102
    /** The platform line separator. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   103
    public static final String lineSeparator = System.getProperty("line.separator");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   104
    /** The platform OS name. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   105
    public static final String osName = System.getProperty("os.name");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   106
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   107
    /** The location of the class files for this test, or null if not set. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   108
    public static final String testClasses = System.getProperty("test.classes");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   109
    /** The location of the source files for this test, or null if not set. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   110
    public static final String testSrc = System.getProperty("test.src");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   111
    /** The location of the test JDK for this test, or null if not set. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   112
    public static final String testJDK = System.getProperty("test.jdk");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   113
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   114
    /** The current directory. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   115
    public static final Path currDir = Paths.get(".");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   116
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   117
    /** The stream used for logging output. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   118
    public PrintStream out = System.err;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   119
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   120
    JavaCompiler compiler;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   121
    StandardJavaFileManager standardJavaFileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   122
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   123
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   124
     * Checks if the host OS is some version of Windows.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   125
     * @return true if the host OS is some version of Windows
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   126
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   127
    public boolean isWindows() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   128
        return osName.toLowerCase(Locale.ENGLISH).startsWith("windows");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   129
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   130
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   131
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   132
     * Splits a string around matches of the given regular expression.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   133
     * If the string is empty, an empty list will be returned.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   134
     * @param text the string to be split
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   135
     * @param sep  the delimiting regular expression
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   136
     * @return the strings between the separators
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   137
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   138
    public List<String> split(String text, String sep) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   139
        if (text.isEmpty())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   140
            return Collections.emptyList();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   141
        return Arrays.asList(text.split(sep));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   142
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   143
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   144
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   145
     * Checks if two lists of strings are equal.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   146
     * @param l1 the first list of strings to be compared
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   147
     * @param l2 the second list of strings to be compared
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   148
     * @throws Error if the lists are not equal
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   149
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   150
    public void checkEqual(List<String> l1, List<String> l2) throws Error {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   151
        if (!Objects.equals(l1, l2)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   152
            // l1 and l2 cannot both be null
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   153
            if (l1 == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   154
                throw new Error("comparison failed: l1 is null");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   155
            if (l2 == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   156
                throw new Error("comparison failed: l2 is null");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   157
            // report first difference
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   158
            for (int i = 0; i < Math.min(l1.size(), l2.size()); i++) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   159
                String s1 = l1.get(i);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   160
                String s2 = l1.get(i);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   161
                if (!Objects.equals(s1, s2)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   162
                    throw new Error("comparison failed, index " + i +
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   163
                            ", (" + s1 + ":" + s2 + ")");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   164
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   165
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   166
            throw new Error("comparison failed: l1.size=" + l1.size() + ", l2.size=" + l2.size());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   167
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   168
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   169
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   170
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   171
     * Filters a list of strings according to the given regular expression.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   172
     * @param regex the regular expression
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   173
     * @param lines the strings to be filtered
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   174
     * @return the strings matching the regular expression
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   175
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   176
    public List<String> grep(String regex, List<String> lines) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   177
        return grep(Pattern.compile(regex), lines);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   178
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   179
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   180
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   181
     * Filters a list of strings according to the given regular expression.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   182
     * @param pattern the regular expression
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   183
     * @param lines the strings to be filtered
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   184
     * @return the strings matching the regular expression
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   185
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   186
    public List<String> grep(Pattern pattern, List<String> lines) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   187
        return lines.stream()
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   188
                .filter(s -> pattern.matcher(s).find())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   189
                .collect(Collectors.toList());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   190
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   191
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   192
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   193
     * Copies a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   194
     * If the given destination exists and is a directory, the copy is created
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   195
     * in that directory.  Otherwise, the copy will be placed at the destination,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   196
     * possibly overwriting any existing file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   197
     * <p>Similar to the shell "cp" command: {@code cp from to}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   198
     * @param from the file to be copied
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   199
     * @param to where to copy the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   200
     * @throws IOException if any error occurred while copying the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   201
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   202
    public void copyFile(String from, String to) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   203
        copyFile(Paths.get(from), Paths.get(to));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   204
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   205
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   206
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   207
     * Copies a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   208
     * If the given destination exists and is a directory, the copy is created
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   209
     * in that directory.  Otherwise, the copy will be placed at the destination,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   210
     * possibly overwriting any existing file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   211
     * <p>Similar to the shell "cp" command: {@code cp from to}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   212
     * @param from the file to be copied
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   213
     * @param to where to copy the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   214
     * @throws IOException if an error occurred while copying the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   215
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   216
    public void copyFile(Path from, Path to) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   217
        if (Files.isDirectory(to)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   218
            to = to.resolve(from.getFileName());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   219
        } else {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   220
            Files.createDirectories(to.getParent());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   221
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   222
        Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   223
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   224
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   225
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   226
     * Creates one of more directories.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   227
     * For each of the series of paths, a directory will be created,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   228
     * including any necessary parent directories.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   229
     * <p>Similar to the shell command: {@code mkdir -p paths}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   230
     * @param paths the directories to be created
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   231
     * @throws IOException if an error occurred while creating the directories
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   232
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   233
    public void createDirectories(String... paths) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   234
        if (paths.length == 0)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   235
            throw new IllegalArgumentException("no directories specified");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   236
        for (String p: paths)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   237
            Files.createDirectories(Paths.get(p));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   238
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   239
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   240
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   241
     * Creates one or more directories.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   242
     * For each of the series of paths, a directory will be created,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   243
     * including any necessary parent directories.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   244
     * <p>Similar to the shell command: {@code mkdir -p paths}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   245
     * @param paths the directories to be created
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   246
     * @throws IOException if an error occurred while creating the directories
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   247
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   248
    public void createDirectories(Path... paths) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   249
        if (paths.length == 0)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   250
            throw new IllegalArgumentException("no directories specified");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   251
        for (Path p: paths)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   252
            Files.createDirectories(p);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   253
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   254
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   255
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   256
     * Deletes one or more files.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   257
     * Any directories to be deleted must be empty.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   258
     * <p>Similar to the shell command: {@code rm files}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   259
     * @param files the files to be deleted
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   260
     * @throws IOException if an error occurred while deleting the files
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   261
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   262
    public void deleteFiles(String... files) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   263
        if (files.length == 0)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   264
            throw new IllegalArgumentException("no files specified");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   265
        for (String file: files)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   266
            Files.delete(Paths.get(file));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   267
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   268
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   269
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   270
     * Moves a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   271
     * If the given destination exists and is a directory, the file will be moved
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   272
     * to that directory.  Otherwise, the file will be moved to the destination,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   273
     * possibly overwriting any existing file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   274
     * <p>Similar to the shell "mv" command: {@code mv from to}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   275
     * @param from the file to be moved
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   276
     * @param to where to move the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   277
     * @throws IOException if an error occurred while moving the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   278
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   279
    public void moveFile(String from, String to) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   280
        moveFile(Paths.get(from), Paths.get(to));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   281
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   282
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   283
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   284
     * Moves a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   285
     * If the given destination exists and is a directory, the file will be moved
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   286
     * to that directory.  Otherwise, the file will be moved to the destination,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   287
     * possibly overwriting any existing file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   288
     * <p>Similar to the shell "mv" command: {@code mv from to}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   289
     * @param from the file to be moved
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   290
     * @param to where to move the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   291
     * @throws IOException if an error occurred while moving the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   292
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   293
    public void moveFile(Path from, Path to) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   294
        if (Files.isDirectory(to)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   295
            to = to.resolve(from.getFileName());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   296
        } else {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   297
            Files.createDirectories(to.getParent());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   298
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   299
        Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   300
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   301
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   302
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   303
     * Reads the lines of a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   304
     * The file is read using the default character encoding.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   305
     * @param path the file to be read
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   306
     * @return the lines of the file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   307
     * @throws IOException if an error occurred while reading the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   308
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   309
    public List<String> readAllLines(String path) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   310
        return readAllLines(path, null);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   311
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   312
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   313
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   314
     * Reads the lines of a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   315
     * The file is read using the default character encoding.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   316
     * @param path the file to be read
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   317
     * @return the lines of the file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   318
     * @throws IOException if an error occurred while reading the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   319
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   320
    public List<String> readAllLines(Path path) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   321
        return readAllLines(path, null);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   322
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   323
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   324
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   325
     * Reads the lines of a file using the given encoding.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   326
     * @param path the file to be read
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   327
     * @param encoding the encoding to be used to read the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   328
     * @return the lines of the file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   329
     * @throws IOException if an error occurred while reading the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   330
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   331
    public List<String> readAllLines(String path, String encoding) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   332
        return readAllLines(Paths.get(path), encoding);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   333
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   334
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   335
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   336
     * Reads the lines of a file using the given encoding.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   337
     * @param path the file to be read
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   338
     * @param encoding the encoding to be used to read the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   339
     * @return the lines of the file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   340
     * @throws IOException if an error occurred while reading the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   341
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   342
    public List<String> readAllLines(Path path, String encoding) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   343
        return Files.readAllLines(path, getCharset(encoding));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   344
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   345
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   346
    private Charset getCharset(String encoding) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   347
        return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   348
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   349
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   350
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   351
     * Writes a file containing the given content.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   352
     * Any necessary directories for the file will be created.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   353
     * @param path where to write the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   354
     * @param content the content for the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   355
     * @throws IOException if an error occurred while writing the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   356
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   357
    public void writeFile(String path, String content) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   358
        writeFile(Paths.get(path), content);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   359
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   360
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   361
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   362
     * Writes a file containing the given content.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   363
     * Any necessary directories for the file will be created.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   364
     * @param path where to write the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   365
     * @param content the content for the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   366
     * @throws IOException if an error occurred while writing the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   367
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   368
    public void writeFile(Path path, String content) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   369
        Path dir = path.getParent();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   370
        if (dir != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   371
            Files.createDirectories(dir);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   372
        try (BufferedWriter w = Files.newBufferedWriter(path)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   373
            w.write(content);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   374
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   375
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   376
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   377
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   378
     * Writes one or more files containing Java source code.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   379
     * For each file to be written, the filename will be inferred from the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   380
     * given base directory, the package declaration (if present) and from the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   381
     * the name of the first class, interface or enum declared in the file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   382
     * <p>For example, if the base directory is /my/dir/ and the content
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   383
     * contains "package p; class C { }", the file will be written to
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   384
     * /my/dir/p/C.java.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   385
     * <p>Note: the content is analyzed using regular expressions;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   386
     * errors can occur if any contents have initial comments that might trip
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   387
     * up the analysis.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   388
     * @param dir the base directory
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   389
     * @param contents the contents of the files to be written
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   390
     * @throws IOException if an error occurred while writing any of the files.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   391
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   392
    public void writeJavaFiles(Path dir, String... contents) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   393
        if (contents.length == 0)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   394
            throw new IllegalArgumentException("no content specified for any files");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   395
        for (String c: contents) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   396
            new JavaSource(c).write(dir);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   397
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   398
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   399
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   400
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   401
     * Returns the path for the binary of a JDK tool within {@link testJDK}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   402
     * @param tool the name of the tool
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   403
     * @return the path of the tool
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   404
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   405
    public Path getJDKTool(String tool) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   406
        return Paths.get(testJDK, "bin", tool);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   407
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   408
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   409
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   410
     * Returns a string representing the contents of an {@code Iterable} as a list.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   411
     * @param <T> the type parameter of the {@code Iterable}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   412
     * @param items the iterable
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   413
     * @return the string
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   414
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   415
    <T> String toString(Iterable<T> items) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   416
        return StreamSupport.stream(items.spliterator(), false)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   417
                .map(Objects::toString)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   418
                .collect(Collectors.joining(",", "[", "]"));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   419
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   420
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   421
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   422
     * The supertype for tasks.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   423
     * Complex operations are modelled by building and running a "Task" object.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   424
     * Tasks are typically configured in a fluent series of calls.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   425
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   426
    public interface Task {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   427
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   428
         * Returns the name of the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   429
         * @return the name of the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   430
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   431
        String name();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   432
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   433
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   434
         * Executes the task as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   435
         * @return a Result object containing the results of running the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   436
         * @throws TaskError if the outcome of the task was not as expected
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   437
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   438
        Result run() throws TaskError;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   439
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   440
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   441
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   442
     * Exception thrown by {@code Task.run} when the outcome is not as
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   443
     * expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   444
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   445
    public static class TaskError extends Error {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   446
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   447
         * Creates a TaskError object with the given message.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   448
         * @param message the message
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   449
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   450
        public TaskError(String message) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   451
            super(message);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   452
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   453
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   454
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   455
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   456
     * An enum to indicate the mode a task should use it is when executed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   457
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   458
    public enum Mode {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   459
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   460
         * The task should use the interface used by the command
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   461
         * line launcher for the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   462
         * For example, for javac: com.sun.tools.javac.Main.compile
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   463
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   464
        CMDLINE,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   465
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   466
         * The task should use a publicly defined API for the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   467
         * For example, for javac: javax.tools.JavaCompiler
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   468
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   469
        API,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   470
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   471
         * The task should use the standard launcher for the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   472
         * For example, $JAVA_HOME/bin/javac
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   473
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   474
        EXEC
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   475
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   476
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   477
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   478
     * An enum to indicate the expected success or failure of executing a task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   479
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   480
    public enum Expect {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   481
        /** It is expected that the task will complete successfully. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   482
        SUCCESS,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   483
        /** It is expected that the task will not complete successfully. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   484
        FAIL
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   485
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   486
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   487
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   488
     * An enum to identify the streams that may be written by a {@code Task}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   489
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   490
    public enum OutputKind {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   491
        /** Identifies output written to {@code System.out} or {@code stdout}. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   492
        STDOUT,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   493
        /** Identifies output written to {@code System.err} or {@code stderr}. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   494
        STDERR,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   495
        /** Identifies output written to a stream provided directly to the task. */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   496
        DIRECT
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   497
    };
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   498
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   499
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   500
     * The results from running a {@link Task}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   501
     * The results contain the exit code returned when the tool was invoked,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   502
     * and a map containing the output written to any streams during the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   503
     * execution of the tool.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   504
     * All tools support "stdout" and "stderr".
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   505
     * Tools that take an explicit PrintWriter save output written to that
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   506
     * stream as "main".
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   507
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   508
    public class Result {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   509
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   510
        final Task task;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   511
        final int exitCode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   512
        final Map<OutputKind, String> outputMap;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   513
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   514
        Result(Task task, int exitCode, Map<OutputKind, String> outputMap) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   515
            this.task = task;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   516
            this.exitCode = exitCode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   517
            this.outputMap = outputMap;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   518
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   519
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   520
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   521
         * Returns the content of a specified stream.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   522
         * @param outputKind the kind of the selected stream
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   523
         * @return the content that was written to that stream when the tool
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   524
         *  was executed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   525
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   526
        public String getOutput(OutputKind outputKind) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   527
            return outputMap.get(outputKind);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   528
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   529
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   530
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   531
         * Returns the content of a named stream as a list of lines.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   532
         * @param outputKind the kind of the selected stream
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   533
         * @return the content that was written to that stream when the tool
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   534
         *  was executed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   535
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   536
        public List<String> getOutputLines(OutputKind outputKind) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   537
            return Arrays.asList(outputMap.get(outputKind).split(lineSeparator));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   538
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   539
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   540
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   541
         * Writes the content of the specified stream to the log.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   542
         * @param kind the kind of the selected stream
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   543
         * @return this Result object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   544
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   545
        public Result write(OutputKind kind) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   546
            String text = getOutput(kind);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   547
            if (text == null || text.isEmpty())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   548
                out.println("[" + task.name() + ":" + kind + "]: empty");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   549
            else {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   550
                out.println("[" + task.name() + ":" + kind + "]:");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   551
                out.print(text);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   552
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   553
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   554
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   555
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   556
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   557
         * Writes the content of all streams with any content to the log.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   558
         * @return this Result object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   559
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   560
        public Result writeAll() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   561
            outputMap.forEach((name, text) -> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   562
                if (!text.isEmpty()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   563
                    out.println("[" + name + "]:");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   564
                    out.print(text);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   565
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   566
            });
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   567
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   568
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   569
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   570
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   571
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   572
     * A utility base class to simplify the implementation of tasks.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   573
     * Provides support for running the task in a process and for
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   574
     * capturing output written by the task to stdout, stderr and
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   575
     * other writers where applicable.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   576
     * @param <T> the implementing subclass
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   577
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   578
    protected static abstract class AbstractTask<T extends AbstractTask<T>> implements Task {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   579
        protected final Mode mode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   580
        private final Map<OutputKind, String> redirects = new EnumMap<>(OutputKind.class);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   581
        private final Map<String, String> envVars = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   582
        private Expect expect = Expect.SUCCESS;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   583
        int expectedExitCode = 0;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   584
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   585
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   586
         * Create a task that will execute in the specified mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   587
         * @param mode the mode
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   588
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   589
        protected AbstractTask(Mode mode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   590
            this.mode = mode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   591
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   592
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   593
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   594
         * Sets the expected outcome of the task and calls {@code run()}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   595
         * @param expect the expected outcome
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   596
         * @return the result of calling {@code run()}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   597
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   598
        public Result run(Expect expect) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   599
            expect(expect, Integer.MIN_VALUE);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   600
            return run();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   601
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   602
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   603
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   604
         * Sets the expected outcome of the task and calls {@code run()}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   605
         * @param expect the expected outcome
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   606
         * @param exitCode the expected exit code if the expected outcome
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   607
         *      is {@code FAIL}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   608
         * @return the result of calling {@code run()}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   609
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   610
        public Result run(Expect expect, int exitCode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   611
            expect(expect, exitCode);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   612
            return run();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   613
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   614
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   615
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   616
         * Sets the expected outcome and expected exit code of the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   617
         * The exit code will not be checked if the outcome is
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   618
         * {@code Expect.SUCCESS} or if the exit code is set to
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   619
         * {@code Integer.MIN_VALUE}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   620
         * @param expect the expected outcome
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   621
         * @param exitCode the expected exit code
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   622
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   623
        protected void expect(Expect expect, int exitCode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   624
            this.expect = expect;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   625
            this.expectedExitCode = exitCode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   626
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   627
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   628
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   629
         * Checks the exit code contained in a {@code Result} against the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   630
         * expected outcome and exit value
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   631
         * @param result the result object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   632
         * @return the result object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   633
         * @throws TaskError if the exit code stored in the result object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   634
         *      does not match the expected outcome and exit code.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   635
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   636
        protected Result checkExit(Result result) throws TaskError {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   637
            switch (expect) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   638
                case SUCCESS:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   639
                    if (result.exitCode != 0) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   640
                        result.writeAll();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   641
                        throw new TaskError("Task " + name() + " failed: rc=" + result.exitCode);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   642
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   643
                    break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   644
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   645
                case FAIL:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   646
                    if (result.exitCode == 0) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   647
                        result.writeAll();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   648
                        throw new TaskError("Task " + name() + " succeeded unexpectedly");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   649
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   650
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   651
                    if (expectedExitCode != Integer.MIN_VALUE
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   652
                            && result.exitCode != expectedExitCode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   653
                        result.writeAll();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   654
                        throw new TaskError("Task " + name() + "failed with unexpected exit code "
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   655
                            + result.exitCode + ", expected " + expectedExitCode);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   656
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   657
                    break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   658
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   659
            return result;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   660
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   661
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   662
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   663
         * Sets an environment variable to be used by this task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   664
         * @param name the name of the environment variable
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   665
         * @param value the value for the environment variable
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   666
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   667
         * @throws IllegalStateException if the task mode is not {@code EXEC}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   668
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   669
        protected T envVar(String name, String value) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   670
            if (mode != Mode.EXEC)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   671
                throw new IllegalStateException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   672
            envVars.put(name, value);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   673
            return (T) this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   674
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   675
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   676
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   677
         * Redirects output from an output stream to a file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   678
         * @param outputKind the name of the stream to be redirected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   679
         * @param path the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   680
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   681
         * @throws IllegalStateException if the task mode is not {@code EXEC}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   682
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   683
        protected T redirect(OutputKind outputKind, String path) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   684
            if (mode != Mode.EXEC)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   685
                throw new IllegalStateException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   686
            redirects.put(outputKind, path);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   687
            return (T) this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   688
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   689
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   690
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   691
         * Returns a {@code ProcessBuilder} initialized with any
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   692
         * redirects and environment variables that have been set.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   693
         * @return a {@code ProcessBuilder}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   694
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   695
        protected ProcessBuilder getProcessBuilder() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   696
            if (mode != Mode.EXEC)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   697
                throw new IllegalStateException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   698
            ProcessBuilder pb = new ProcessBuilder();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   699
            if (redirects.get(OutputKind.STDOUT) != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   700
                pb.redirectOutput(new File(redirects.get(OutputKind.STDOUT)));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   701
            if (redirects.get(OutputKind.STDERR) != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   702
                pb.redirectError(new File(redirects.get(OutputKind.STDERR)));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   703
            pb.environment().putAll(envVars);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   704
            return pb;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   705
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   706
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   707
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   708
         * Collects the output from a process and saves it in a {@code Result}.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   709
         * @param tb the {@code ToolBox} containing the task {@code t}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   710
         * @param t the task initiating the process
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   711
         * @param p the process
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   712
         * @return a Result object containing the output from the process and its
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   713
         *      exit value.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   714
         * @throws InterruptedException if the thread is interrupted
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   715
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   716
        protected Result runProcess(ToolBox tb, Task t, Process p) throws InterruptedException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   717
            if (mode != Mode.EXEC)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   718
                throw new IllegalStateException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   719
            ProcessOutput sysOut = new ProcessOutput(p.getInputStream()).start();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   720
            ProcessOutput sysErr = new ProcessOutput(p.getErrorStream()).start();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   721
            sysOut.waitUntilDone();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   722
            sysErr.waitUntilDone();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   723
            int rc = p.waitFor();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   724
            Map<OutputKind, String> outputMap = new EnumMap<>(OutputKind.class);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   725
            outputMap.put(OutputKind.STDOUT, sysOut.getOutput());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   726
            outputMap.put(OutputKind.STDERR, sysErr.getOutput());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   727
            return checkExit(tb.new Result(t, rc, outputMap));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   728
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   729
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   730
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   731
         * Thread-friendly class to read the output from a process until the stream
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   732
         * is exhausted.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   733
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   734
        static class ProcessOutput implements Runnable {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   735
            ProcessOutput(InputStream from) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   736
                in = new BufferedReader(new InputStreamReader(from));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   737
                out = new StringBuilder();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   738
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   739
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   740
            ProcessOutput start() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   741
                new Thread(this).start();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   742
                return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   743
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   744
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   745
            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   746
            public void run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   747
                try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   748
                    String line;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   749
                    while ((line = in.readLine()) != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   750
                        out.append(line).append("\n");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   751
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   752
                } catch (IOException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   753
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   754
                synchronized (this) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   755
                    done = true;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   756
                    notifyAll();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   757
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   758
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   759
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   760
            synchronized void waitUntilDone() throws InterruptedException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   761
                boolean interrupted = false;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   762
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   763
                // poll interrupted flag, while waiting for copy to complete
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   764
                while (!(interrupted = Thread.interrupted()) && !done)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   765
                    wait(1000);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   766
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   767
                if (interrupted)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   768
                    throw new InterruptedException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   769
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   770
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   771
            String getOutput() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   772
                return out.toString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   773
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   774
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   775
            private BufferedReader in;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   776
            private final StringBuilder out;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   777
            private boolean done;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   778
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   779
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   780
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   781
         * Utility class to simplify the handling of temporarily setting a
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   782
         * new stream for System.out or System.err.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   783
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   784
        static class StreamOutput {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   785
            // Functional interface to set a stream.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   786
            // Expected use: System::setOut, System::setErr
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   787
            private interface Initializer {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   788
                void set(PrintStream s);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   789
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   790
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   791
            private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   792
            private final PrintStream ps = new PrintStream(baos);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   793
            private final PrintStream prev;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   794
            private final Initializer init;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   795
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   796
            StreamOutput(PrintStream s, Initializer init) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   797
                prev = s;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   798
                init.set(ps);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   799
                this.init = init;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   800
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   801
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   802
            /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   803
             * Closes the stream and returns the contents that were written to it.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   804
             * @return the contents that were written to it.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   805
             */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   806
            String close() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   807
                init.set(prev);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   808
                ps.close();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   809
                return baos.toString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   810
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   811
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   812
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   813
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   814
         * Utility class to simplify the handling of creating an in-memory PrintWriter.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   815
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   816
        static class WriterOutput {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   817
            private final StringWriter sw = new StringWriter();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   818
            final PrintWriter pw = new PrintWriter(sw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   819
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   820
            /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   821
             * Closes the stream and returns the contents that were written to it.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   822
             * @return the contents that were written to it.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   823
             */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   824
            String close() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   825
                pw.close();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   826
                return sw.toString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   827
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   828
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   829
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   830
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   831
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   832
     * A task to configure and run the Java compiler, javac.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   833
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   834
    public class JavacTask extends AbstractTask<JavacTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   835
        private boolean includeStandardOptions;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   836
        private String classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   837
        private String sourcepath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   838
        private String outdir;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   839
        private List<String> options;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   840
        private List<String> classes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   841
        private List<String> files;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   842
        private List<JavaFileObject> fileObjects;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   843
        private JavaFileManager fileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   844
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   845
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   846
         * Creates a task to execute {@code javac} using API mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   847
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   848
        public JavacTask() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   849
            super(Mode.API);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   850
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   851
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   852
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   853
         * Creates a task to execute {@code javac} in a specified mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   854
         * @param mode the mode to be used
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   855
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   856
        public JavacTask(Mode mode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   857
            super(mode);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   858
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   859
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   860
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   861
         * Sets the classpath.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   862
         * @param classpath the classpath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   863
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   864
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   865
        public JavacTask classpath(String classpath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   866
            this.classpath = classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   867
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   868
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   869
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   870
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   871
         * Sets the sourcepath.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   872
         * @param sourcepath the sourcepath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   873
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   874
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   875
        public JavacTask sourcepath(String sourcepath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   876
            this.sourcepath = sourcepath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   877
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   878
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   879
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   880
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   881
         * Sets the output directory.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   882
         * @param outdir the output directory
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   883
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   884
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   885
        public JavacTask outdir(String outdir) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   886
            this.outdir = outdir;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   887
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   888
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   889
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   890
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   891
         * Sets the options.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   892
         * @param options the options
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   893
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   894
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   895
        public JavacTask options(String... options) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   896
            this.options = Arrays.asList(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   897
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   898
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   899
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   900
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   901
         * Sets the classes to be analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   902
         * @param classes the classes
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   903
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   904
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   905
        public JavacTask classes(String... classes) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   906
            this.classes = Arrays.asList(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   907
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   908
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   909
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   910
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   911
         * Sets the files to be compiled or analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   912
         * @param files the files
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   913
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   914
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   915
        public JavacTask files(String... files) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   916
            this.files = Arrays.asList(files);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   917
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   918
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   919
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   920
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   921
         * Sets the files to be compiled or analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   922
         * @param files the files
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   923
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   924
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   925
        public JavacTask files(Path... files) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   926
            this.files = Stream.of(files)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   927
                    .map(Path::toString)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   928
                    .collect(Collectors.toList());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   929
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   930
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   931
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   932
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   933
         * Sets the sources to be compiled or analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   934
         * Each source string is converted into an in-memory object that
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   935
         * can be passed directly to the compiler.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   936
         * @param sources the sources
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   937
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   938
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   939
        public JavacTask sources(String... sources) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   940
            fileObjects = Stream.of(sources)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   941
                    .map(s -> new JavaSource(s))
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   942
                    .collect(Collectors.toList());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   943
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   944
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   945
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   946
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   947
         * Sets the file manager to be used by this task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   948
         * @param fileManager the file manager
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   949
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   950
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   951
        public JavacTask fileManager(JavaFileManager fileManager) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   952
            this.fileManager = fileManager;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   953
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   954
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   955
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   956
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   957
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   958
         * @return the name "javac"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   959
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   960
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   961
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   962
            return "javac";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   963
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   964
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   965
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   966
         * Calls the compiler with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   967
         * @return a Result object indicating the outcome of the compilation
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   968
         * and the content of any output written to stdout, stderr, or the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   969
         * main stream by the compiler.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   970
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   971
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   972
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   973
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   974
            if (mode == Mode.EXEC)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   975
                return runExec();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   976
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   977
            WriterOutput direct = new WriterOutput();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   978
            // The following are to catch output to System.out and System.err,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   979
            // in case these are used instead of the primary (main) stream
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   980
            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   981
            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   982
            int rc;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   983
            Map<OutputKind, String> outputMap = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   984
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   985
                switch (mode == null ? Mode.API : mode) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   986
                    case API:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   987
                        rc = runAPI(direct.pw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   988
                        break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   989
                    case CMDLINE:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   990
                        rc = runCommand(direct.pw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   991
                        break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   992
                    default:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   993
                        throw new IllegalStateException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   994
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   995
            } catch (IOException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   996
                out.println("Exception occurred: " + e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   997
                rc = 99;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   998
            } finally {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
   999
                outputMap.put(OutputKind.STDOUT, sysOut.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1000
                outputMap.put(OutputKind.STDERR, sysErr.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1001
                outputMap.put(OutputKind.DIRECT, direct.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1002
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1003
            return checkExit(new Result(this, rc, outputMap));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1004
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1005
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1006
        private int runAPI(PrintWriter pw) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1007
//            if (compiler == null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1008
                // TODO: allow this to be set externally
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1009
//                compiler = ToolProvider.getSystemJavaCompiler();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1010
                compiler = JavacTool.create();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1011
//            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1012
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1013
            if (fileManager == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1014
                fileManager = compiler.getStandardFileManager(null, null, null);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1015
            if (outdir != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1016
                setLocation(StandardLocation.CLASS_OUTPUT, toFiles(outdir));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1017
            if (classpath != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1018
                setLocation(StandardLocation.CLASS_PATH, toFiles(classpath));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1019
            if (sourcepath != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1020
                setLocation(StandardLocation.SOURCE_PATH, toFiles(sourcepath));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1021
            List<String> allOpts = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1022
            if (options != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1023
                allOpts.addAll(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1024
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1025
            Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1026
            JavaCompiler.CompilationTask task = compiler.getTask(pw,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1027
                    fileManager,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1028
                    null,  // diagnostic listener; should optionally collect diags
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1029
                    allOpts,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1030
                    classes,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1031
                    allFiles);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1032
            return ((JavacTaskImpl) task).doCall().exitCode;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1033
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1034
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1035
        private void setLocation(StandardLocation location, List<File> files) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1036
            if (!(fileManager instanceof StandardJavaFileManager))
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1037
                throw new IllegalStateException("not a StandardJavaFileManager");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1038
            ((StandardJavaFileManager) fileManager).setLocation(location, files);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1039
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1040
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1041
        private int runCommand(PrintWriter pw) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1042
            List<String> args = getAllArgs();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1043
            String[] argsArray = args.toArray(new String[args.size()]);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1044
            return com.sun.tools.javac.Main.compile(argsArray, pw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1045
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1046
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1047
        private Result runExec() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1048
            List<String> args = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1049
            Path javac = getJDKTool("javac");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1050
            args.add(javac.toString());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1051
            if (includeStandardOptions) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1052
                args.addAll(split(System.getProperty("test.tool.vm.opts"), " +"));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1053
                args.addAll(split(System.getProperty("test.compiler.opts"), " +"));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1054
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1055
            args.addAll(getAllArgs());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1056
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1057
            String[] argsArray = args.toArray(new String[args.size()]);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1058
            ProcessBuilder pb = getProcessBuilder();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1059
            pb.command(argsArray);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1060
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1061
                return runProcess(ToolBox.this, this, pb.start());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1062
            } catch (IOException | InterruptedException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1063
                throw new Error(e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1064
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1065
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1066
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1067
        private List<String> getAllArgs() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1068
            List<String> args = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1069
            if (options != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1070
                args.addAll(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1071
            if (outdir != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1072
                args.add("-d");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1073
                args.add(outdir);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1074
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1075
            if (classpath != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1076
                args.add("-classpath");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1077
                args.add(classpath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1078
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1079
            if (sourcepath != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1080
                args.add("-sourcepath");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1081
                args.add(sourcepath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1082
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1083
            if (classes != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1084
                args.addAll(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1085
            if (files != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1086
                args.addAll(files);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1087
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1088
            return args;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1089
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1090
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1091
        private List<File> toFiles(String path) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1092
            List<File> result = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1093
            for (String s: path.split(File.pathSeparator)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1094
                if (!s.isEmpty())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1095
                    result.add(new File(s));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1096
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1097
            return result;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1098
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1099
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1100
        private Iterable<? extends JavaFileObject> joinFiles(
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1101
                List<String> files, List<JavaFileObject> fileObjects) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1102
            if (files == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1103
                return fileObjects;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1104
            if (standardJavaFileManager == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1105
                standardJavaFileManager = compiler.getStandardFileManager(null, null, null);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1106
            Iterable<? extends JavaFileObject> filesAsFileObjects =
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1107
                    standardJavaFileManager.getJavaFileObjectsFromStrings(files);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1108
            if (fileObjects == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1109
                return filesAsFileObjects;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1110
            List<JavaFileObject> combinedList = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1111
            for (JavaFileObject o: filesAsFileObjects)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1112
                combinedList.add(o);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1113
            combinedList.addAll(fileObjects);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1114
            return combinedList;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1115
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1116
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1117
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1118
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1119
     * A task to configure and run the native header tool, javah.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1120
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1121
    public class JavahTask extends AbstractTask<JavahTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1122
        private String classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1123
        private List<String> options;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1124
        private List<String> classes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1125
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1126
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1127
         * Create a task to execute {@code javah} using {@code CMDLINE} mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1128
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1129
        public JavahTask() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1130
            super(Mode.CMDLINE);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1131
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1132
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1133
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1134
         * Sets the classpath.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1135
         * @param classpath the classpath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1136
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1137
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1138
        public JavahTask classpath(String classpath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1139
            this.classpath = classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1140
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1141
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1142
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1143
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1144
         * Sets the options.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1145
         * @param options the options
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1146
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1147
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1148
        public JavahTask options(String... options) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1149
            this.options = Arrays.asList(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1150
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1151
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1152
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1153
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1154
         * Sets the classes to be analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1155
         * @param classes the classes
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1156
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1157
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1158
        public JavahTask classes(String... classes) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1159
            this.classes = Arrays.asList(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1160
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1161
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1162
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1163
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1164
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1165
         * @return the name "javah"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1166
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1167
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1168
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1169
            return "javah";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1170
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1171
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1172
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1173
         * Calls the javah tool with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1174
         * @return a Result object indicating the outcome of the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1175
         * and the content of any output written to stdout, stderr, or the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1176
         * main stream provided to the task.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1177
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1178
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1179
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1180
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1181
            List<String> args = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1182
            if (options != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1183
                args.addAll(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1184
            if (classpath != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1185
                args.add("-classpath");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1186
                args.add(classpath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1187
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1188
            if (classes != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1189
                args.addAll(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1190
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1191
            WriterOutput direct = new WriterOutput();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1192
            // These are to catch output to System.out and System.err,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1193
            // in case these are used instead of the primary streams
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1194
            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1195
            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1196
            int rc;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1197
            Map<OutputKind, String> outputMap = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1198
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1199
                rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), direct.pw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1200
            } finally {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1201
                outputMap.put(OutputKind.STDOUT, sysOut.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1202
                outputMap.put(OutputKind.STDERR, sysErr.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1203
                outputMap.put(OutputKind.DIRECT, direct.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1204
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1205
            return checkExit(new Result(this, rc, outputMap));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1206
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1207
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1208
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1209
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1210
     * A task to configure and run the disassembler tool, javap.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1211
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1212
    public class JavapTask extends AbstractTask<JavapTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1213
        private String classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1214
        private List<String> options;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1215
        private List<String> classes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1216
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1217
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1218
         * Create a task to execute {@code javap} using {@code CMDLINE} mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1219
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1220
        public JavapTask() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1221
            super(Mode.CMDLINE);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1222
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1223
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1224
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1225
         * Sets the classpath.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1226
         * @param classpath the classpath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1227
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1228
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1229
        public JavapTask classpath(String classpath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1230
            this.classpath = classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1231
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1232
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1233
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1234
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1235
         * Sets the options.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1236
         * @param options the options
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1237
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1238
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1239
        public JavapTask options(String... options) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1240
            this.options = Arrays.asList(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1241
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1242
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1243
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1244
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1245
         * Sets the classes to be analyzed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1246
         * @param classes the classes
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1247
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1248
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1249
        public JavapTask classes(String... classes) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1250
            this.classes = Arrays.asList(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1251
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1252
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1253
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1254
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1255
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1256
         * @return the name "javap"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1257
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1258
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1259
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1260
            return "javap";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1261
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1262
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1263
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1264
         * Calls the javap tool with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1265
         * @return a Result object indicating the outcome of the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1266
         * and the content of any output written to stdout, stderr, or the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1267
         * main stream.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1268
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1269
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1270
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1271
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1272
            List<String> args = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1273
            if (options != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1274
                args.addAll(options);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1275
            if (classpath != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1276
                args.add("-classpath");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1277
                args.add(classpath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1278
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1279
            if (classes != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1280
                args.addAll(classes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1281
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1282
            WriterOutput direct = new WriterOutput();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1283
            // These are to catch output to System.out and System.err,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1284
            // in case these are used instead of the primary streams
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1285
            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1286
            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1287
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1288
            int rc;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1289
            Map<OutputKind, String> outputMap = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1290
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1291
                rc = com.sun.tools.javap.Main.run(args.toArray(new String[args.size()]), direct.pw);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1292
            } finally {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1293
                outputMap.put(OutputKind.STDOUT, sysOut.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1294
                outputMap.put(OutputKind.STDERR, sysErr.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1295
                outputMap.put(OutputKind.DIRECT, direct.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1296
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1297
            return checkExit(new Result(this, rc, outputMap));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1298
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1299
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1300
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1301
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1302
     * A task to configure and run the jar file utility.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1303
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1304
    public class JarTask extends AbstractTask<JarTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1305
        private Path jar;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1306
        private Manifest manifest;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1307
        private String classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1308
        private String mainClass;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1309
        private Path baseDir;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1310
        private List<Path> paths;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1311
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1312
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1313
         * Creates a task to write jar files, using API mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1314
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1315
        public JarTask() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1316
            super(Mode.API);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1317
            paths = Collections.emptyList();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1318
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1319
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1320
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1321
         * Creates a JarTask for use with a given jar file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1322
         * @param path the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1323
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1324
        public JarTask(String path) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1325
            this();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1326
            jar = Paths.get(path);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1327
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1328
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1329
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1330
         * Sets a manifest for the jar file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1331
         * @param manifest the manifest
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1332
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1333
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1334
        public JarTask manifest(Manifest manifest) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1335
            this.manifest = manifest;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1336
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1337
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1338
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1339
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1340
         * Sets a manifest for the jar file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1341
         * @param manifest a string containing the contents of the manifest
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1342
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1343
         * @throws IOException if there is a problem creating the manifest
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1344
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1345
        public JarTask manifest(String manifest) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1346
            this.manifest = new Manifest(new ByteArrayInputStream(manifest.getBytes()));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1347
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1348
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1349
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1350
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1351
         * Sets the classpath to be written to the {@code Class-Path}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1352
         * entry in the manifest.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1353
         * @param classpath the classpath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1354
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1355
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1356
        public JarTask classpath(String classpath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1357
            this.classpath = classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1358
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1359
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1360
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1361
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1362
         * Sets the class to be written to the {@code Main-Class}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1363
         * entry in the manifest..
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1364
         * @param mainClass the name of the main class
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1365
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1366
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1367
        public JarTask mainClass(String mainClass) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1368
            this.mainClass = mainClass;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1369
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1370
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1371
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1372
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1373
         * Sets the base directory for files to be written into the jar file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1374
         * @param baseDir the base directory
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1375
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1376
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1377
        public JarTask baseDir(String baseDir) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1378
            this.baseDir = Paths.get(baseDir);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1379
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1380
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1381
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1382
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1383
         * Sets the files to be written into the jar file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1384
         * @param files the files
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1385
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1386
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1387
        public JarTask files(String... files) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1388
            this.paths = Stream.of(files)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1389
                    .map(file -> Paths.get(file))
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1390
                    .collect(Collectors.toList());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1391
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1392
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1393
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1394
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1395
         * Provides limited jar command-like functionality.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1396
         * The supported commands are:
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1397
         * <ul>
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1398
         * <li> jar cf jarfile -C dir files...
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1399
         * <li> jar cfm jarfile manifestfile -C dir files...
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1400
         * </ul>
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1401
         * Any values specified by other configuration methods will be ignored.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1402
         * @param args arguments in the style of those for the jar command
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1403
         * @return a Result object containing the results of running the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1404
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1405
        public Result run(String... args) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1406
            if (args.length < 2)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1407
                throw new IllegalArgumentException();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1408
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1409
            ListIterator<String> iter = Arrays.asList(args).listIterator();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1410
            String first = iter.next();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1411
            switch (first) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1412
                case "cf":
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1413
                    jar = Paths.get(iter.next());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1414
                    break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1415
                case "cfm":
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1416
                    jar = Paths.get(iter.next());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1417
                    try (InputStream in = Files.newInputStream(Paths.get(iter.next()))) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1418
                        manifest = new Manifest(in);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1419
                    } catch (IOException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1420
                        throw new IOError(e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1421
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1422
                    break;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1423
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1424
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1425
            if (iter.hasNext()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1426
                if (iter.next().equals("-C"))
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1427
                    baseDir = Paths.get(iter.next());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1428
                else
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1429
                    iter.previous();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1430
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1431
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1432
            paths = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1433
            while (iter.hasNext())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1434
                paths.add(Paths.get(iter.next()));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1435
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1436
            return run();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1437
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1438
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1439
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1440
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1441
         * @return the name "jar"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1442
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1443
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1444
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1445
            return "jar";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1446
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1447
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1448
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1449
         * Creates a jar file with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1450
         * @return a Result object indicating the outcome of the compilation
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1451
         * and the content of any output written to stdout, stderr, or the
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1452
         * main stream by the compiler.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1453
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1454
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1455
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1456
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1457
            Manifest m = (manifest == null) ? new Manifest() : manifest;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1458
            Attributes mainAttrs = m.getMainAttributes();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1459
            if (mainClass != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1460
                mainAttrs.put(Attributes.Name.MAIN_CLASS, mainClass);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1461
            if (classpath != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1462
                mainAttrs.put(Attributes.Name.CLASS_PATH, classpath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1463
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1464
            StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1465
            StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1466
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1467
            int rc;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1468
            Map<OutputKind, String> outputMap = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1469
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1470
            try (OutputStream os = Files.newOutputStream(jar);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1471
                    JarOutputStream jos = openJar(os, m)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1472
                Path base = (baseDir == null) ? currDir : baseDir;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1473
                for (Path path: paths) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1474
                    Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1475
                        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1476
                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1477
                            try {
27389
301be76491af 8063074: test/tools/javac/plugin/showType/Test.java fails on Windows
jjg
parents: 27385
diff changeset
  1478
                                String p = base.relativize(file)
301be76491af 8063074: test/tools/javac/plugin/showType/Test.java fails on Windows
jjg
parents: 27385
diff changeset
  1479
                                        .normalize()
301be76491af 8063074: test/tools/javac/plugin/showType/Test.java fails on Windows
jjg
parents: 27385
diff changeset
  1480
                                        .toString()
301be76491af 8063074: test/tools/javac/plugin/showType/Test.java fails on Windows
jjg
parents: 27385
diff changeset
  1481
                                        .replace(File.separatorChar, '/');
301be76491af 8063074: test/tools/javac/plugin/showType/Test.java fails on Windows
jjg
parents: 27385
diff changeset
  1482
                                JarEntry e = new JarEntry(p);
26100
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1483
                                jos.putNextEntry(e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1484
                                jos.write(Files.readAllBytes(file));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1485
                                jos.closeEntry();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1486
                                return FileVisitResult.CONTINUE;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1487
                            } catch (IOException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1488
                                System.err.println("Error adding " + file + " to jar file: " + e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1489
                                return FileVisitResult.TERMINATE;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1490
                            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1491
                        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1492
                    });
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1493
                }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1494
                rc = 0;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1495
            } catch (IOException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1496
                System.err.println("Error opening " + jar + ": " + e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1497
                rc = 1;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1498
            } finally {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1499
                outputMap.put(OutputKind.STDOUT, sysOut.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1500
                outputMap.put(OutputKind.STDERR, sysErr.close());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1501
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1502
            return checkExit(new Result(this, rc, outputMap));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1503
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1504
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1505
        private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1506
            if (m == null || m.getMainAttributes().isEmpty() && m.getEntries().isEmpty()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1507
                return new JarOutputStream(os);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1508
            } else {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1509
                if (m.getMainAttributes().get(Attributes.Name.MANIFEST_VERSION) == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1510
                    m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1511
                return new JarOutputStream(os, m);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1512
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1513
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1514
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1515
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1516
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1517
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1518
     * A task to configure and run the Java launcher.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1519
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1520
    public class JavaTask extends AbstractTask<JavaTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1521
        boolean includeStandardOptions = true;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1522
        private String classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1523
        private List<String> vmOptions;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1524
        private String className;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1525
        private List<String> classArgs;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1526
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1527
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1528
         * Create a task to run the Java launcher, using {@code EXEC} mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1529
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1530
        public JavaTask() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1531
            super(Mode.EXEC);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1532
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1533
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1534
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1535
         * Sets the classpath.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1536
         * @param classpath the classpath
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1537
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1538
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1539
        public JavaTask classpath(String classpath) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1540
            this.classpath = classpath;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1541
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1542
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1543
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1544
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1545
         * Sets the VM options.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1546
         * @param vmOptions the options
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1547
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1548
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1549
        public JavaTask vmOptions(String... vmOptions) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1550
            this.vmOptions = Arrays.asList(vmOptions);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1551
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1552
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1553
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1554
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1555
         * Sets the name of the class to be executed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1556
         * @param className the name of the class
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1557
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1558
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1559
        public JavaTask className(String className) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1560
            this.className = className;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1561
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1562
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1563
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1564
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1565
         * Sets the arguments for the class to be executed.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1566
         * @param classArgs the arguments
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1567
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1568
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1569
        public JavaTask classArgs(String... classArgs) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1570
            this.classArgs = Arrays.asList(classArgs);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1571
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1572
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1573
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1574
        /**
26392
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1575
         * Sets whether or not the standard VM and java options for the test should be passed
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1576
         * to the new VM instance. If this method is not called, the default behavior is that
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1577
         * the options will be passed to the new VM instance.
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1578
         *
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1579
         * @param includeStandardOptions whether or not the standard VM and java options for
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1580
         *                               the test should be passed to the new VM instance.
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1581
         * @return this task object
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1582
         */
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1583
        public JavaTask includeStandardOptions(boolean includeStandardOptions) {
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1584
            this.includeStandardOptions = includeStandardOptions;
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1585
            return this;
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1586
        }
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1587
2bda2002e2f2 8047675: tools/javac/defaultMethods/Assertions.java fails if run with -enableassertions (-ea)
jlahoda
parents: 26100
diff changeset
  1588
        /**
26100
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1589
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1590
         * @return the name "java"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1591
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1592
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1593
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1594
            return "java";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1595
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1596
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1597
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1598
         * Calls the Java launcher with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1599
         * @return a Result object indicating the outcome of the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1600
         * and the content of any output written to stdout or stderr.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1601
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1602
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1603
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1604
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1605
            List<String> args = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1606
            args.add(getJDKTool("java").toString());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1607
            if (includeStandardOptions) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1608
                args.addAll(split(System.getProperty("test.vm.opts"), " +"));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1609
                args.addAll(split(System.getProperty("test.java.opts"), " +"));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1610
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1611
            if (classpath != null) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1612
                args.add("-classpath");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1613
                args.add(classpath);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1614
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1615
            if (vmOptions != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1616
                args.addAll(vmOptions);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1617
            if (className != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1618
                args.add(className);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1619
            if (classArgs != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1620
                args.addAll(classArgs);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1621
            ProcessBuilder pb = getProcessBuilder();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1622
            pb.command(args);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1623
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1624
                return runProcess(ToolBox.this, this, pb.start());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1625
            } catch (IOException | InterruptedException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1626
                throw new Error(e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1627
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1628
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1629
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1630
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1631
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1632
     * A task to configure and run a general command.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1633
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1634
    public class ExecTask extends AbstractTask<ExecTask> {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1635
        private final String command;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1636
        private List<String> args;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1637
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1638
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1639
         * Create a task to execute a given command, to be run using {@code EXEC} mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1640
         * @param command the command to be executed
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1641
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1642
        public ExecTask(String command) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1643
            super(Mode.EXEC);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1644
            this.command = command;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1645
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1646
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1647
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1648
         * Create a task to execute a given command, to be run using {@code EXEC} mode.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1649
         * @param command the command to be executed
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1650
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1651
        public ExecTask(Path command) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1652
            super(Mode.EXEC);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1653
            this.command = command.toString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1654
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1655
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1656
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1657
         * Sets the arguments for the command to be executed
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1658
         * @param args the arguments
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1659
         * @return this task object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1660
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1661
        public ExecTask args(String... args) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1662
            this.args = Arrays.asList(args);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1663
            return this;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1664
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1665
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1666
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1667
         * {@inheritDoc}
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1668
         * @return the name "exec"
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1669
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1670
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1671
        public String name() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1672
            return "exec";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1673
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1674
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1675
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1676
         * Calls the command with the arguments as currently configured.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1677
         * @return a Result object indicating the outcome of the task
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1678
         * and the content of any output written to stdout or stderr.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1679
         * @throws TaskError if the outcome of the task is not as expected.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1680
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1681
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1682
        public Result run() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1683
            List<String> cmdArgs = new ArrayList<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1684
            cmdArgs.add(command);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1685
            if (args != null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1686
                cmdArgs.addAll(args);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1687
            ProcessBuilder pb = getProcessBuilder();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1688
            pb.command(cmdArgs);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1689
            try {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1690
                return runProcess(ToolBox.this, this, pb.start());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1691
            } catch (IOException | InterruptedException e) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1692
                throw new Error(e);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1693
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1694
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1695
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1696
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1697
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1698
     * An in-memory Java source file.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1699
     * It is able to extract the file name from simple source text using
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1700
     * regular expressions.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1701
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1702
    public static class JavaSource extends SimpleJavaFileObject {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1703
        private final String source;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1704
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1705
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1706
         * Creates a in-memory file object for Java source code.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1707
         * @param className the name of the class
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1708
         * @param source the source text
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1709
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1710
        public JavaSource(String className, String source) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1711
            super(URI.create(className), JavaFileObject.Kind.SOURCE);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1712
            this.source = source;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1713
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1714
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1715
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1716
         * Creates a in-memory file object for Java source code.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1717
         * The name of the class will be inferred from the source code.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1718
         * @param source the source text
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1719
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1720
        public JavaSource(String source) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1721
            super(URI.create(getJavaFileNameFromSource(source)),
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1722
                    JavaFileObject.Kind.SOURCE);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1723
            this.source = source;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1724
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1725
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1726
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1727
         * Writes the source code to a file in the current directory.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1728
         * @throws IOException if there is a problem writing the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1729
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1730
        public void write() throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1731
            write(currDir);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1732
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1733
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1734
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1735
         * Writes the source code to a file in a specified directory.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1736
         * @param dir the directory
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1737
         * @throws IOException if there is a problem writing the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1738
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1739
        public void write(Path dir) throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1740
            Path file = dir.resolve(getJavaFileNameFromSource(source));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1741
            Files.createDirectories(file.getParent());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1742
            try (BufferedWriter out = Files.newBufferedWriter(file)) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1743
                out.write(source.replace("\n", lineSeparator));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1744
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1745
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1746
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1747
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1748
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1749
            return source;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1750
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1751
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1752
        private static Pattern packagePattern =
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1753
                Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1754
        private static Pattern classPattern =
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1755
                Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1756
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1757
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1758
         * Extracts the Java file name from the class declaration.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1759
         * This method is intended for simple files and uses regular expressions,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1760
         * so comments matching the pattern can make the method fail.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1761
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1762
        static String getJavaFileNameFromSource(String source) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1763
            String packageName = null;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1764
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1765
            Matcher matcher = packagePattern.matcher(source);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1766
            if (matcher.find())
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1767
                packageName = matcher.group(1).replace(".", "/");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1768
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1769
            matcher = classPattern.matcher(source);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1770
            if (matcher.find()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1771
                String className = matcher.group(1) + ".java";
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1772
                return (packageName == null) ? className : packageName + "/" + className;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1773
            } else {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1774
                throw new Error("Could not extract the java class " +
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1775
                        "name from the provided source");
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1776
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1777
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1778
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1779
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1780
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1781
     * Extracts the Java file name from the class declaration.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1782
     * This method is intended for simple files and uses regular expressions,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1783
     * so comments matching the pattern can make the method fail.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1784
     * @deprecated This is a legacy method for compatibility with ToolBox v1.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1785
     *      Use {@link JavaSource#getName JavaSource.getName} instead.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1786
     * @param source the source text
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1787
     * @return the Java file name inferred from the source
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1788
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1789
    @Deprecated
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1790
    public static String getJavaFileNameFromSource(String source) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1791
        return JavaSource.getJavaFileNameFromSource(source);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1792
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1793
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1794
    /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1795
     * A memory file manager, for saving generated files in memory.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1796
     * The file manager delegates to a separate file manager for listing and
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1797
     * reading input files.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1798
     */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1799
    public static class MemoryFileManager extends ForwardingJavaFileManager {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1800
        private interface Content {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1801
            byte[] getBytes();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1802
            String getString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1803
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1804
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1805
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1806
         * Maps binary class names to generated content.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1807
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1808
        final Map<Location, Map<String, Content>> files;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1809
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1810
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1811
         * Construct a memory file manager which stores output files in memory,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1812
         * and delegates to a default file manager for input files.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1813
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1814
        public MemoryFileManager() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1815
            this(JavacTool.create().getStandardFileManager(null, null, null));
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1816
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1817
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1818
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1819
         * Construct a memory file manager which stores output files in memory,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1820
         * and delegates to a specified file manager for input files.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1821
         * @param fileManager the file manager to be used for input files
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1822
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1823
        public MemoryFileManager(JavaFileManager fileManager) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1824
            super(fileManager);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1825
            files = new HashMap<>();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1826
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1827
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1828
        @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1829
        public JavaFileObject getJavaFileForOutput(Location location,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1830
                                                   String name,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1831
                                                   JavaFileObject.Kind kind,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1832
                                                   FileObject sibling)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1833
        {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1834
            return new MemoryFileObject(location, name, kind);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1835
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1836
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1837
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1838
         * Returns the content written to a file in a given location,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1839
         * or null if no such file has been written.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1840
         * @param location the location
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1841
         * @param name the name of the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1842
         * @return the content as an array of bytes
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1843
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1844
        public byte[] getFileBytes(Location location, String name) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1845
            Content content = getFile(location, name);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1846
            return (content == null) ? null : content.getBytes();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1847
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1848
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1849
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1850
         * Returns the content written to a file in a given location,
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1851
         * or null if no such file has been written.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1852
         * @param location the location
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1853
         * @param name the name of the file
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1854
         * @return the content as a string
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1855
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1856
        public String getFileString(Location location, String name) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1857
            Content content = getFile(location, name);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1858
            return (content == null) ? null : content.getString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1859
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1860
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1861
        private Content getFile(Location location, String name) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1862
            Map<String, Content> filesForLocation = files.get(location);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1863
            return (filesForLocation == null) ? null : filesForLocation.get(name);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1864
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1865
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1866
        private void save(Location location, String name, Content content) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1867
            Map<String, Content> filesForLocation = files.get(location);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1868
            if (filesForLocation == null)
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1869
                files.put(location, filesForLocation = new HashMap<>());
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1870
            filesForLocation.put(name, content);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1871
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1872
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1873
        /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1874
         * A writable file object stored in memory.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1875
         */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1876
        private class MemoryFileObject extends SimpleJavaFileObject {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1877
            private final Location location;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1878
            private final String name;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1879
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1880
            /**
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1881
             * Constructs a memory file object.
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1882
             * @param name binary name of the class to be stored in this file object
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1883
             */
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1884
            MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1885
                super(URI.create("mfm:///" + name.replace('.','/') + kind.extension),
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1886
                      Kind.CLASS);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1887
                this.location = location;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1888
                this.name = name;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1889
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1890
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1891
            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1892
            public OutputStream openOutputStream() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1893
                return new FilterOutputStream(new ByteArrayOutputStream()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1894
                    @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1895
                    public void close() throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1896
                        out.close();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1897
                        byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1898
                        save(location, name, new Content() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1899
                            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1900
                            public byte[] getBytes() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1901
                                return bytes;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1902
                            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1903
                            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1904
                            public String getString() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1905
                                return new String(bytes);
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1906
                            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1907
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1908
                        });
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1909
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1910
                };
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1911
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1912
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1913
            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1914
            public Writer openWriter() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1915
                return new FilterWriter(new StringWriter()) {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1916
                    @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1917
                    public void close() throws IOException {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1918
                        out.close();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1919
                        String text = ((StringWriter) out).toString();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1920
                        save(location, name, new Content() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1921
                            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1922
                            public byte[] getBytes() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1923
                                return text.getBytes();
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1924
                            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1925
                            @Override
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1926
                            public String getString() {
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1927
                                return text;
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1928
                            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1929
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1930
                        });
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1931
                    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1932
                };
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1933
            }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1934
        }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1935
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1936
    }
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1937
bb7dd001d190 8050429: Update/cleanup ToolBox
jjg
parents:
diff changeset
  1938
}