/*
 * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package toolbox;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;

/**
 * Utility methods and classes for writing jtreg tests for
 * javac, javah, and javap. (For javadoc support, see JavadocTester.)
 *
 * <p>There is support for common file operations similar to
 * shell commands like cat, cp, diff, mv, rm, grep.
 *
 * <p>There is also support for invoking various tools, like
 * javac, javah, javap, jar, java and other JDK tools.
 *
 * <p><em>File separators</em>: for convenience, many operations accept strings
 * to represent filenames. On all platforms on which JDK is supported,
 * "/" is a legal filename component separator. In particular, even
 * on Windows, where the official file separator is "\", "/" is a legal
 * alternative. It is therefore recommended that any client code using
 * strings to specify filenames should use "/".
 *
 * @author Vicente Romero (original)
 * @author Jonathan Gibbons (revised)
 */
public class ToolBox {
    /** The platform line separator. */
    public static final String lineSeparator = System.getProperty("line.separator");
    /** The platform path separator. */
    public static final String pathSeparator = System.getProperty("path.separator");
    /** The platform file separator character. */
    public static char fileSeparatorChar = System.getProperty("file.separator").charAt(0);
    /** The platform OS name. */
    public static final String osName = System.getProperty("os.name");

    /** The location of the class files for this test, or null if not set. */
    public static final String testClasses = System.getProperty("test.classes");
    /** The location of the source files for this test, or null if not set. */
    public static final String testSrc = System.getProperty("test.src");
    /** The location of the test JDK for this test, or null if not set. */
    public static final String testJDK = System.getProperty("test.jdk");
    /** The timeout factor for slow systems. */
    public static final float timeoutFactor;
    static {
        String ttf = System.getProperty("test.timeout.factor");
        timeoutFactor = (ttf == null) ? 1.0f : Float.parseFloat(ttf);
    }

    /** The current directory. */
    public static final Path currDir = Path.of(".");

    /** The stream used for logging output. */
    public PrintStream out = System.err;

    /**
     * Checks if the host OS is some version of Windows.
     * @return true if the host OS is some version of Windows
     */
    public static boolean isWindows() {
        return osName.toLowerCase(Locale.ENGLISH).startsWith("windows");
    }

    /**
     * Splits a string around matches of the given regular expression.
     * If the string is empty, an empty list will be returned.
     *
     * @param text the string to be split
     * @param sep  the delimiting regular expression
     * @return the strings between the separators
     */
    public List<String> split(String text, String sep) {
        if (text.isEmpty())
            return Collections.emptyList();
        return Arrays.asList(text.split(sep));
    }

    /**
     * Checks if two lists of strings are equal.
     *
     * @param l1 the first list of strings to be compared
     * @param l2 the second list of strings to be compared
     * @throws Error if the lists are not equal
     */
    public void checkEqual(List<String> l1, List<String> l2) throws Error {
        if (!Objects.equals(l1, l2)) {
            // l1 and l2 cannot both be null
            if (l1 == null)
                throw new Error("comparison failed: l1 is null");
            if (l2 == null)
                throw new Error("comparison failed: l2 is null");
            // report first difference
            for (int i = 0; i < Math.min(l1.size(), l2.size()); i++) {
                String s1 = l1.get(i);
                String s2 = l2.get(i);
                if (!Objects.equals(s1, s2)) {
                    throw new Error("comparison failed, index " + i +
                            ", (" + s1 + ":" + s2 + ")");
                }
            }
            throw new Error("comparison failed: l1.size=" + l1.size() + ", l2.size=" + l2.size());
        }
    }

    /**
     * Filters a list of strings according to the given regular expression,
     * returning the strings that match the regular expression.
     *
     * @param regex the regular expression
     * @param lines the strings to be filtered
     * @return the strings matching the regular expression
     */
    public List<String> grep(String regex, List<String> lines) {
        return grep(Pattern.compile(regex), lines, true);
    }

    /**
     * Filters a list of strings according to the given regular expression,
     * returning the strings that match the regular expression.
     *
     * @param pattern the regular expression
     * @param lines   the strings to be filtered
     * @return the strings matching the regular expression
     */
    public List<String> grep(Pattern pattern, List<String> lines) {
        return grep(pattern, lines, true);
    }

    /**
     * Filters a list of strings according to the given regular expression,
     * returning either the strings that match or the strings that do not match.
     *
     * @param regex the regular expression
     * @param lines the strings to be filtered
     * @param match if true, return the lines that match; otherwise if false, return the lines that do not match.
     * @return the strings matching(or not matching) the regular expression
     */
    public List<String> grep(String regex, List<String> lines, boolean match) {
        return grep(Pattern.compile(regex), lines, match);
    }

    /**
     * Filters a list of strings according to the given regular expression,
     * returning either the strings that match or the strings that do not match.
     *
     * @param pattern the regular expression
     * @param lines   the strings to be filtered
     * @param match   if true, return the lines that match; otherwise if false, return the lines that do not match.
     * @return the strings matching(or not matching) the regular expression
     */
    public List<String> grep(Pattern pattern, List<String> lines, boolean match) {
        return lines.stream()
                .filter(s -> pattern.matcher(s).find() == match)
                .collect(Collectors.toList());
    }

    /**
     * Copies a file.
     * If the given destination exists and is a directory, the copy is created
     * in that directory.  Otherwise, the copy will be placed at the destination,
     * possibly overwriting any existing file.
     * <p>Similar to the shell "cp" command: {@code cp from to}.
     *
     * @param from the file to be copied
     * @param to   where to copy the file
     * @throws IOException if any error occurred while copying the file
     */
    public void copyFile(String from, String to) throws IOException {
        copyFile(Path.of(from), Path.of(to));
    }

    /**
     * Copies a file.
     * If the given destination exists and is a directory, the copy is created
     * in that directory.  Otherwise, the copy will be placed at the destination,
     * possibly overwriting any existing file.
     * <p>Similar to the shell "cp" command: {@code cp from to}.
     *
     * @param from the file to be copied
     * @param to   where to copy the file
     * @throws IOException if an error occurred while copying the file
     */
    public void copyFile(Path from, Path to) throws IOException {
        if (Files.isDirectory(to)) {
            to = to.resolve(from.getFileName());
        } else if (to.getParent() != null) {
            Files.createDirectories(to.getParent());
        }
        Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * Copies the contents of a directory to another directory.
     * <p>Similar to the shell command: {@code rsync fromDir/ toDir/}.
     *
     * @param fromDir the directory containing the files to be copied
     * @param toDir   the destination to which to copy the files
     */
    public void copyDir(String fromDir, String toDir) {
        copyDir(Path.of(fromDir), Path.of(toDir));
    }

    /**
     * Copies the contents of a directory to another directory.
     * The destination direction should not already exist.
     * <p>Similar to the shell command: {@code rsync fromDir/ toDir/}.
     *
     * @param fromDir the directory containing the files to be copied
     * @param toDir   the destination to which to copy the files
     */
    public void copyDir(Path fromDir, Path toDir) {
        try {
            if (toDir.getParent() != null) {
                Files.createDirectories(toDir.getParent());
            }
            Files.walkFileTree(fromDir, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path fromSubdir, BasicFileAttributes attrs)
                        throws IOException {
                    Files.copy(fromSubdir, toDir.resolve(fromDir.relativize(fromSubdir)));
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path fromFile, BasicFileAttributes attrs)
                        throws IOException {
                    Files.copy(fromFile, toDir.resolve(fromDir.relativize(fromFile)));
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            throw new Error("Could not copy " + fromDir + " to " + toDir + ": " + e, e);
        }
    }

    /**
     * Creates one or more directories.
     * For each of the series of paths, a directory will be created,
     * including any necessary parent directories.
     * <p>Similar to the shell command: {@code mkdir -p paths}.
     *
     * @param paths the directories to be created
     * @throws IOException if an error occurred while creating the directories
     */
    public void createDirectories(String... paths) throws IOException {
        if (paths.length == 0)
            throw new IllegalArgumentException("no directories specified");
        for (String p : paths)
            Files.createDirectories(Path.of(p));
    }

    /**
     * Creates one or more directories.
     * For each of the series of paths, a directory will be created,
     * including any necessary parent directories.
     * <p>Similar to the shell command: {@code mkdir -p paths}.
     *
     * @param paths the directories to be created
     * @throws IOException if an error occurred while creating the directories
     */
    public void createDirectories(Path... paths) throws IOException {
        if (paths.length == 0)
            throw new IllegalArgumentException("no directories specified");
        for (Path p : paths)
            Files.createDirectories(p);
    }

    /**
     * Deletes one or more files, awaiting confirmation that the files
     * no longer exist. Any directories to be deleted must be empty.
     * <p>Similar to the shell command: {@code rm files}.
     *
     * @param files the names of the files to be deleted
     * @throws IOException if an error occurred while deleting the files
     */
    public void deleteFiles(String... files) throws IOException {
        deleteFiles(List.of(files).stream().map(Paths::get).collect(Collectors.toList()));
    }

    /**
     * Deletes one or more files, awaiting confirmation that the files
     * no longer exist. Any directories to be deleted must be empty.
     * <p>Similar to the shell command: {@code rm files}.
     *
     * @param paths the paths for the files to be deleted
     * @throws IOException if an error occurred while deleting the files
     */
    public void deleteFiles(Path... paths) throws IOException {
        deleteFiles(List.of(paths));
    }

    /**
     * Deletes one or more files, awaiting confirmation that the files
     * no longer exist. Any directories to be deleted must be empty.
     * <p>Similar to the shell command: {@code rm files}.
     *
     * @param paths the paths for the files to be deleted
     * @throws IOException if an error occurred while deleting the files
     */
    public void deleteFiles(List<Path> paths) throws IOException {
        if (paths.isEmpty())
            throw new IllegalArgumentException("no files specified");
        IOException ioe = null;
        for (Path path : paths) {
            ioe = deleteFile(path, ioe);
        }
        if (ioe != null) {
            throw ioe;
        }
        ensureDeleted(paths);
    }

    /**
     * Deletes all content of a directory (but not the directory itself),
     * awaiting confirmation that the content has been deleted.
     *
     * @param root the directory to be cleaned
     * @throws IOException if an error occurs while cleaning the directory
     */
    public void cleanDirectory(Path root) throws IOException {
        if (!Files.isDirectory(root)) {
            throw new IOException(root + " is not a directory");
        }
        Files.walkFileTree(root, new SimpleFileVisitor<>() {
            private IOException ioe = null;
            // for each directory we visit, maintain a list of the files that we try to delete
            private final Deque<List<Path>> dirFiles = new LinkedList<>();

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes a) {
                ioe = deleteFile(file, ioe);
                dirFiles.peekFirst().add(file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes a) {
                if (!dir.equals(root)) {
                    dirFiles.peekFirst().add(dir);
                }
                dirFiles.addFirst(new ArrayList<>());
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
                if (e != null) {
                    throw e;
                }
                if (ioe != null) {
                    throw ioe;
                }
                ensureDeleted(dirFiles.removeFirst());
                if (!dir.equals(root)) {
                    ioe = deleteFile(dir, ioe);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    /**
     * Internal method to delete a file, using {@code Files.delete}.
     * It does not wait to confirm deletion, nor does it retry.
     * If an exception occurs it is either returned or added to the set of
     * suppressed exceptions for an earlier exception.
     *
     * @param path the path for the file to be deleted
     * @param ioe  the earlier exception, or null
     * @return the earlier exception or an exception that occurred while
     * trying to delete the file
     */
    private IOException deleteFile(Path path, IOException ioe) {
        try {
            Files.delete(path);
        } catch (IOException e) {
            if (ioe == null) {
                ioe = e;
            } else {
                ioe.addSuppressed(e);
            }
        }
        return ioe;
    }

    /**
     * Wait until it is confirmed that a set of files have been deleted.
     *
     * @param paths the paths for the files to be deleted
     * @throws IOException if a file has not been deleted
     */
    private void ensureDeleted(Collection<Path> paths)
            throws IOException {
        for (Path path : paths) {
            ensureDeleted(path);
        }
    }

    /**
     * Wait until it is confirmed that a file has been deleted.
     *
     * @param path the path for the file to be deleted
     * @throws IOException if problems occur while deleting the file
     */
    private void ensureDeleted(Path path) throws IOException {
        long startTime = System.currentTimeMillis();
        do {
            // Note: Files.notExists is not the same as !Files.exists
            if (Files.notExists(path)) {
                return;
            }
            System.gc(); // allow finalizers and cleaners to run
            try {
                Thread.sleep(RETRY_DELETE_MILLIS);
            } catch (InterruptedException e) {
                throw new IOException("Interrupted while waiting for file to be deleted: " + path, e);
            }
        } while ((System.currentTimeMillis() - startTime) <= MAX_RETRY_DELETE_MILLIS);

        throw new IOException("File not deleted: " + path);
    }

    private static final int RETRY_DELETE_MILLIS = isWindows() ? (int)(500 * timeoutFactor): 0;
    private static final int MAX_RETRY_DELETE_MILLIS = isWindows() ? (int)(15 * 1000 * timeoutFactor) : 0;

    /**
     * Moves a file.
     * If the given destination exists and is a directory, the file will be moved
     * to that directory.  Otherwise, the file will be moved to the destination,
     * possibly overwriting any existing file.
     * <p>Similar to the shell "mv" command: {@code mv from to}.
     *
     * @param from the file to be moved
     * @param to   where to move the file
     * @throws IOException if an error occurred while moving the file
     */
    public void moveFile(String from, String to) throws IOException {
        moveFile(Path.of(from), Path.of(to));
    }

    /**
     * Moves a file.
     * If the given destination exists and is a directory, the file will be moved
     * to that directory.  Otherwise, the file will be moved to the destination,
     * possibly overwriting any existing file.
     * <p>Similar to the shell "mv" command: {@code mv from to}.
     *
     * @param from the file to be moved
     * @param to   where to move the file
     * @throws IOException if an error occurred while moving the file
     */
    public void moveFile(Path from, Path to) throws IOException {
        if (Files.isDirectory(to)) {
            to = to.resolve(from.getFileName());
        } else {
            Files.createDirectories(to.getParent());
        }
        Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
    }

    /**
     * Reads the lines of a file.
     * The file is read using the default character encoding.
     *
     * @param path the file to be read
     * @return the lines of the file
     * @throws IOException if an error occurred while reading the file
     */
    public List<String> readAllLines(String path) throws IOException {
        return readAllLines(path, null);
    }

    /**
     * Reads the lines of a file.
     * The file is read using the default character encoding.
     *
     * @param path the file to be read
     * @return the lines of the file
     * @throws IOException if an error occurred while reading the file
     */
    public List<String> readAllLines(Path path) throws IOException {
        return readAllLines(path, null);
    }

    /**
     * Reads the lines of a file using the given encoding.
     *
     * @param path     the file to be read
     * @param encoding the encoding to be used to read the file
     * @return the lines of the file.
     * @throws IOException if an error occurred while reading the file
     */
    public List<String> readAllLines(String path, String encoding) throws IOException {
        return readAllLines(Path.of(path), encoding);
    }

    /**
     * Reads the lines of a file using the given encoding.
     *
     * @param path     the file to be read
     * @param encoding the encoding to be used to read the file
     * @return the lines of the file
     * @throws IOException if an error occurred while reading the file
     */
    public List<String> readAllLines(Path path, String encoding) throws IOException {
        return Files.readAllLines(path, getCharset(encoding));
    }

    private Charset getCharset(String encoding) {
        return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding);
    }

    /**
     * Find .java files in one or more directories.
     * <p>Similar to the shell "find" command: {@code find paths -name \*.java}.
     *
     * @param paths the directories in which to search for .java files
     * @return the .java files found
     * @throws IOException if an error occurred while searching for files
     */
    public Path[] findJavaFiles(Path... paths) throws IOException {
        return findFiles(".java", paths);
    }

    /**
     * Find files matching the file extension, in one or more directories.
     * <p>Similar to the shell "find" command: {@code find paths -name \*.ext}.
     *
     * @param fileExtension the extension to search for
     * @param paths         the directories in which to search for files
     * @return the files matching the file extension
     * @throws IOException if an error occurred while searching for files
     */
    public Path[] findFiles(String fileExtension, Path... paths) throws IOException {
        Set<Path> files = new TreeSet<>();  // use TreeSet to force a consistent order
        for (Path p : paths) {
            Files.walkFileTree(p, new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                    if (file.getFileName().toString().endsWith(fileExtension)) {
                        files.add(file);
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        }
        return files.toArray(new Path[0]);
    }

    /**
     * Writes a file containing the given content.
     * Any necessary directories for the file will be created.
     *
     * @param path    where to write the file
     * @param content the content for the file
     * @throws IOException if an error occurred while writing the file
     */
    public void writeFile(String path, String content) throws IOException {
        writeFile(Path.of(path), content);
    }

    /**
     * Writes a file containing the given content.
     * Any necessary directories for the file will be created.
     *
     * @param path    where to write the file
     * @param content the content for the file
     * @throws IOException if an error occurred while writing the file
     */
    public void writeFile(Path path, String content) throws IOException {
        Path dir = path.getParent();
        if (dir != null)
            Files.createDirectories(dir);
        try (BufferedWriter w = Files.newBufferedWriter(path)) {
            w.write(content);
        }
    }

    /**
     * Writes one or more files containing Java source code.
     * For each file to be written, the filename will be inferred from the
     * given base directory, the package declaration (if present) and from the
     * the name of the first class, interface or enum declared in the file.
     * <p>For example, if the base directory is /my/dir/ and the content
     * contains "package p; class C { }", the file will be written to
     * /my/dir/p/C.java.
     * <p>Note: the content is analyzed using regular expressions;
     * errors can occur if any contents have initial comments that might trip
     * up the analysis.
     *
     * @param dir      the base directory
     * @param contents the contents of the files to be written
     * @throws IOException if an error occurred while writing any of the files.
     */
    public void writeJavaFiles(Path dir, String... contents) throws IOException {
        if (contents.length == 0)
            throw new IllegalArgumentException("no content specified for any files");
        for (String c : contents) {
            new JavaSource(c).write(dir);
        }
    }

    /**
     * Returns the path for the binary of a JDK tool within {@link #testJDK}.
     *
     * @param tool the name of the tool
     * @return the path of the tool
     */
    public Path getJDKTool(String tool) {
        return Path.of(testJDK, "bin", tool);
    }

    /**
     * Returns a string representing the contents of an {@code Iterable} as a list.
     *
     * @param <T>   the type parameter of the {@code Iterable}
     * @param items the iterable
     * @return the string
     */
    <T> String toString(Iterable<T> items) {
        return StreamSupport.stream(items.spliterator(), false)
                .map(Objects::toString)
                .collect(Collectors.joining(",", "[", "]"));
    }


    /**
     * An in-memory Java source file.
     * It is able to extract the file name from simple source text using
     * regular expressions.
     */
    public static class JavaSource extends SimpleJavaFileObject {
        private final String source;

        /**
         * Creates a in-memory file object for Java source code.
         *
         * @param className the name of the class
         * @param source    the source text
         */
        public JavaSource(String className, String source) {
            super(URI.create(className), JavaFileObject.Kind.SOURCE);
            this.source = source;
        }

        /**
         * Creates a in-memory file object for Java source code.
         * The name of the class will be inferred from the source code.
         *
         * @param source the source text
         */
        public JavaSource(String source) {
            super(URI.create(getJavaFileNameFromSource(source)),
                    JavaFileObject.Kind.SOURCE);
            this.source = source;
        }

        /**
         * Writes the source code to a file in the current directory.
         *
         * @throws IOException if there is a problem writing the file
         */
        public void write() throws IOException {
            write(currDir);
        }

        /**
         * Writes the source code to a file in a specified directory.
         *
         * @param dir the directory
         * @throws IOException if there is a problem writing the file
         */
        public void write(Path dir) throws IOException {
            Path file = dir.resolve(getJavaFileNameFromSource(source));
            Files.createDirectories(file.getParent());
            try (BufferedWriter out = Files.newBufferedWriter(file)) {
                out.write(source.replace("\n", lineSeparator));
            }
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return source;
        }

        private final static Pattern commentPattern =
                Pattern.compile("(?s)(\\s+//.*?\n|/\\*.*?\\*/)");
        private final static Pattern importModulePattern =
                Pattern.compile("import\\s+module\\s+(((?:\\w+\\.)*)\\w+);");
        private final static Pattern modulePattern =
                Pattern.compile("module\\s+((?:\\w+\\.)*)");
        private final static Pattern packagePattern =
                Pattern.compile("package\\s+(((?:\\w+\\.)*)\\w+)");
        private final static Pattern classPattern =
                Pattern.compile("(?:public\\s+)?(?:class|enum|interface|record)\\s+((\\w|\\$)+)");

        /**
         * Extracts the Java file name from the class declaration.
         * This method is intended for simple files and uses regular expressions.
         * Comments in the source are stripped before looking for the
         * declarations from which the name is derived.
         */
        static String getJavaFileNameFromSource(String source) {
            source = removeMatchingSpans(source, commentPattern);
            source = removeMatchingSpans(source, importModulePattern);

            Matcher matcher;

            String packageName = null;

            matcher = modulePattern.matcher(source);
            if (matcher.find())
                return "module-info.java";

            matcher = packagePattern.matcher(source);
            if (matcher.find()) {
                packageName = matcher.group(1).replace(".", "/");
                validateName(packageName);
            }

            matcher = classPattern.matcher(source);
            if (matcher.find()) {
                String className = matcher.group(1) + ".java";
                validateName(className);
                return (packageName == null) ? className : packageName + "/" + className;
            } else if (packageName != null) {
                return packageName + "/package-info.java";
            } else {
                throw new Error("Could not extract the java class " +
                        "name from the provided source");
            }
        }

        static String removeMatchingSpans(String source, Pattern toRemove) {
            StringBuilder sb = new StringBuilder();
            Matcher matcher = toRemove.matcher(source);
            int start = 0;

            while (matcher.find()) {
                sb.append(source, start, matcher.start());
                start = matcher.end();
            }

            sb.append(source.substring(start));
            return sb.toString();
        }
    }

    /**
     * Extracts the Java file name from the class declaration.
     * This method is intended for simple files and uses regular expressions,
     * so comments matching the pattern can make the method fail.
     *
     * @param source the source text
     * @return the Java file name inferred from the source
     * @deprecated This is a legacy method for compatibility with ToolBox v1.
     * Use {@link JavaSource#getName JavaSource.getName} instead.
     */
    @Deprecated
    public static String getJavaFileNameFromSource(String source) {
        return JavaSource.getJavaFileNameFromSource(source);
    }

    private static final Set<String> RESERVED_NAMES = Set.of(
        "con", "prn", "aux", "nul",
        "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8",  "com9",
        "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8",  "lpt9"
    );

    /**
     * Validates if a given name is a valid file name
     * or path name on known platforms.
     *
     * @param name the name
     * @throws IllegalArgumentException if the name is a reserved name
     */
    public static void validateName(String name) {
        for (String part : name.split("[./\\\\]")) {
            if (RESERVED_NAMES.contains(part.toLowerCase(Locale.US))) {
                throw new IllegalArgumentException("Name: " + name + " is" +
                                                   "a reserved name on Windows, " +
                                                   "and will not work!");
            }
        }
    }

    public static class MemoryFileManager extends ForwardingJavaFileManager<JavaFileManager> {
        private interface Content {
            byte[] getBytes();
            String getString();
        }

        /**
         * Maps binary class names to generated content.
         */
        private final Map<Location, Map<String, Content>> files;

        /**
         * Constructs a memory file manager which stores output files in memory,
         * and delegates to a default file manager for input files.
         */
        public MemoryFileManager() {
            this(ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null));
        }

        /**
         * Constructs a memory file manager which stores output files in memory,
         * and delegates to a specified file manager for input files.
         *
         * @param fileManager the file manager to be used for input files
         */
        public MemoryFileManager(JavaFileManager fileManager) {
            super(fileManager);
            files = new HashMap<>();
        }

        @Override
        public JavaFileObject getJavaFileForOutput(Location location,
                                                   String name,
                                                   JavaFileObject.Kind kind,
                                                   FileObject sibling)
        {
            return new MemoryFileObject(location, name, kind);
        }

        /**
         * Returns the set of names of files that have been written to a given
         * location.
         *
         * @param location the location
         * @return the set of file names
         */
        public Set<String> getFileNames(Location location) {
            Map<String, Content> filesForLocation = files.get(location);
            return (filesForLocation == null)
                ? Collections.emptySet() : filesForLocation.keySet();
        }

        /**
         * Returns the content written to a file in a given location,
         * or null if no such file has been written.
         *
         * @param location the location
         * @param name     the name of the file
         * @return the content as an array of bytes
         */
        public byte[] getFileBytes(Location location, String name) {
            Content content = getFile(location, name);
            return (content == null) ? null : content.getBytes();
        }

        /**
         * Returns the content written to a file in a given location,
         * or null if no such file has been written.
         *
         * @param location the location
         * @param name     the name of the file
         * @return the content as a string
         */
        public String getFileString(Location location, String name) {
            Content content = getFile(location, name);
            return (content == null) ? null : content.getString();
        }

        private Content getFile(Location location, String name) {
            Map<String, Content> filesForLocation = files.get(location);
            return (filesForLocation == null) ? null : filesForLocation.get(name);
        }

        private void save(Location location, String name, Content content) {
            files.computeIfAbsent(location, k -> new HashMap<>())
                    .put(name, content);
        }

        /**
         * A writable file object stored in memory.
         */
        private class MemoryFileObject extends SimpleJavaFileObject {
            private final Location location;
            private final String name;

            /**
             * Constructs a memory file object.
             *
             * @param location the location in which to save the file object
             * @param name     binary name of the class to be stored in this file object
             * @param kind     the kind of file object
             */
            MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) {
                super(URI.create("mfm:///" + name.replace('.','/') + kind.extension),
                      Kind.CLASS);
                this.location = location;
                this.name = name;
            }

            @Override
            public OutputStream openOutputStream() {
                return new FilterOutputStream(new ByteArrayOutputStream()) {
                    @Override
                    public void close() throws IOException {
                        out.close();
                        byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
                        save(location, name, new Content() {
                            @Override
                            public byte[] getBytes() {
                                return bytes;
                            }
                            @Override
                            public String getString() {
                                return new String(bytes);
                            }

                        });
                    }
                };
            }

            @Override
            public Writer openWriter() {
                return new FilterWriter(new StringWriter()) {
                    @Override
                    public void close() throws IOException {
                        out.close();
                        String text = out.toString();
                        save(location, name, new Content() {
                            @Override
                            public byte[] getBytes() {
                                return text.getBytes();
                            }
                            @Override
                            public String getString() {
                                return text;
                            }

                        });
                    }
                };
            }
        }
    }
}
