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