jdk/make/src/classes/build/tools/module/ImageBuilder.java
author chegar
Wed, 03 Dec 2014 14:22:58 +0000
changeset 27565 729f9700483a
child 27934 2b4d774b50dc
permissions -rw-r--r--
8049367: Modular Run-Time Images Reviewed-by: chegar, dfuchs, ihse, joehw, mullan, psandoz, wetmore Contributed-by: alan.bateman@oracle.com, alex.buckley@oracle.com, bradford.wetmore@oracle.com, chris.hegarty@oracle.com, erik.joelsson@oracle.com, james.laskey@oracle.com, jonathan.gibbons@oracle.com, karen.kinnear@oracle.com, magnus.ihse.bursie@oracle.com, mandy.chung@oracle.com, mark.reinhold@oracle.com, paul.sandoz@oracle.com, sundararajan.athijegannathan@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27565
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     1
/*
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     2
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     4
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    10
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    15
 * accompanied this code).
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    16
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    20
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    23
 * questions.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    24
 */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    25
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    26
package build.tools.module;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    27
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    28
import jdk.internal.jimage.Archive;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    29
import jdk.internal.jimage.ImageFile;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    30
import jdk.internal.jimage.ImageModules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    31
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    32
import java.io.BufferedReader;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    33
import java.io.File;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    34
import java.io.IOException;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    35
import java.io.InputStream;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    36
import java.io.InputStreamReader;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    37
import java.io.PrintWriter;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    38
import java.io.UncheckedIOException;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    39
import java.nio.ByteOrder;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    40
import java.nio.file.Files;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    41
import java.nio.file.InvalidPathException;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    42
import java.nio.file.Path;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    43
import java.nio.file.Paths;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    44
import java.nio.file.attribute.PosixFilePermission;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    45
import java.util.ArrayList;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    46
import java.util.Collection;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    47
import java.util.HashMap;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    48
import java.util.HashSet;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    49
import java.util.LinkedList;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    50
import java.util.List;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    51
import java.util.Map;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    52
import java.util.Optional;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    53
import java.util.Set;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    54
import java.util.stream.Collectors;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    55
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    56
/**
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    57
 * A tool for building a runtime image.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    58
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    59
 * java build.tools.module.ImageBuilder <options> --output <path> top/modules.xml,...
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    60
 *  Possible options are:
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    61
 *  --cmds                  Location of native commands
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    62
 *  --configs               Location of config files
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    63
 *  --help                  Print this usage message
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    64
 *  --classes               Location of module classes files
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    65
 *  --libs                  Location of native libraries
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    66
 *  --mods                  Comma separated list of module names
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    67
 *  --output                Location of the output path
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    68
 *  --endian                Byte order of the target runtime; {little,big}
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    69
 */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    70
class ImageBuilder {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    71
    static class BadArgs extends Exception {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    72
        private static final long serialVersionUID = 0L;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    73
        BadArgs(String format, Object... args) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    74
            super(String.format(format, args));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    75
            this.format = format;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    76
            this.args = args;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    77
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    78
        BadArgs showUsage(boolean b) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    79
            showUsage = b;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    80
            return this;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    81
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    82
        final String format;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    83
        final Object[] args;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    84
        boolean showUsage;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    85
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    86
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    87
    static abstract class Option {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    88
        final boolean hasArg;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    89
        final String[] aliases;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    90
        Option(boolean hasArg, String... aliases) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    91
            this.hasArg = hasArg;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    92
            this.aliases = aliases;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    93
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    94
        boolean isHidden() {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    95
            return false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    96
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    97
        boolean matches(String opt) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    98
            for (String a : aliases) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    99
                if (a.equals(opt)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   100
                    return true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   101
                } else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   102
                    return true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   103
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   104
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   105
            return false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   106
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   107
        boolean ignoreRest() {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   108
            return false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   109
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   110
        abstract void process(ImageBuilder task, String opt, String arg) throws BadArgs;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   111
        abstract String description();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   112
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   113
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   114
    private static Path CWD = Paths.get("");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   115
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   116
    private static List<Path> splitPath(String arg, String separator)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   117
        throws BadArgs
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   118
    {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   119
        List<Path> paths = new ArrayList<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   120
        for (String p: arg.split(separator)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   121
            if (p.length() > 0) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   122
                try {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   123
                    Path path = CWD.resolve(p);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   124
                    if (Files.notExists(path))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   125
                        throw new BadArgs("path not found: %s", path);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   126
                    paths.add(path);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   127
                } catch (InvalidPathException x) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   128
                    throw new BadArgs("path not valid: %s", p);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   129
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   130
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   131
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   132
        return paths;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   133
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   134
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   135
    static Option[] recognizedOptions = {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   136
        new Option(true, "--cmds") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   137
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   138
                task.options.cmds = splitPath(arg, File.pathSeparator);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   139
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   140
            String description() { return "Location of native commands"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   141
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   142
        new Option(true, "--configs") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   143
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   144
                task.options.configs = splitPath(arg, File.pathSeparator);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   145
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   146
            String description() { return "Location of config files"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   147
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   148
        new Option(false, "--help") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   149
            void process(ImageBuilder task, String opt, String arg) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   150
                task.options.help = true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   151
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   152
            String description() { return "Print this usage message"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   153
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   154
        new Option(true, "--classes") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   155
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   156
                task.options.classes = splitPath(arg, File.pathSeparator);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   157
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   158
            String description() { return "Location of module classes files"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   159
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   160
        new Option(true, "--libs") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   161
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   162
                task.options.libs = splitPath(arg, File.pathSeparator);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   163
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   164
            String description() { return "Location of native libraries"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   165
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   166
        new Option(true, "--mods") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   167
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   168
                for (String mn : arg.split(",")) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   169
                    if (mn.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   170
                        throw new BadArgs("Module not found", mn);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   171
                    task.options.mods.add(mn);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   172
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   173
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   174
            String description() { return "Comma separated list of module names"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   175
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   176
        new Option(true, "--output") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   177
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   178
                Path path = Paths.get(arg);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   179
                task.options.output = path;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   180
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   181
            String description() { return "Location of the output path"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   182
        },
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   183
        new Option(true, "--endian") {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   184
            void process(ImageBuilder task, String opt, String arg) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   185
                if (arg.equals("little"))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   186
                    task.options.endian = ByteOrder.LITTLE_ENDIAN;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   187
                else if (arg.equals("big"))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   188
                    task.options.endian = ByteOrder.BIG_ENDIAN;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   189
                else
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   190
                    throw new BadArgs("Unknown byte order " + arg);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   191
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   192
            String description() { return "Byte order of the target runtime; {little,big}"; }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   193
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   194
    };
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   195
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   196
    private final Options options = new Options();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   197
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   198
    private PrintWriter log;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   199
    void setLog(PrintWriter out) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   200
        log = out;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   201
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   202
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   203
    Set<Module> moduleGraph = new java.util.HashSet<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   204
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   205
    /** Module list files */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   206
    private static final String BOOT_MODULES = "boot.modules";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   207
    private static final String EXT_MODULES = "ext.modules";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   208
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   209
    /**
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   210
     * Result codes.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   211
     */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   212
    static final int EXIT_OK = 0,       // Completed with no errors.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   213
                     EXIT_ERROR = 1,    // Completed but reported errors.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   214
                     EXIT_CMDERR = 2,   // Bad command-line arguments
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   215
                     EXIT_SYSERR = 3,   // System error or resource exhaustion.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   216
                     EXIT_ABNORMAL = 4; // terminated abnormally
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   217
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   218
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   219
    static class Options {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   220
        boolean help;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   221
        List<Path> classes;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   222
        List<Path> cmds;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   223
        List<Path> configs;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   224
        List<Path> libs;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   225
        Set<String> mods = new HashSet<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   226
        Path output;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   227
        ByteOrder endian = ByteOrder.nativeOrder(); // default, if not specified
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   228
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   229
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   230
    public static void main(String[] args) throws Exception {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   231
        ImageBuilder builder = new ImageBuilder();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   232
        int rc = builder.run(args);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   233
        System.exit(rc);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   234
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   235
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   236
    int run(String[] args) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   237
        if (log == null)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   238
            log = new PrintWriter(System.out);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   239
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   240
        try {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   241
            handleOptions(args);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   242
            if (options.help) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   243
                showHelp();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   244
                return EXIT_OK;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   245
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   246
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   247
            if (options.classes == null)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   248
                throw new BadArgs("--classes must be specified").showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   249
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   250
            Path output = options.output;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   251
            if (output == null)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   252
                throw new BadArgs("--output must be specified").showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   253
            Files.createDirectories(output);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   254
            if (Files.list(output).findFirst().isPresent())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   255
                throw new BadArgs("dir not empty", output);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   256
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   257
            if (options.mods.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   258
                throw new BadArgs("--mods must be specified").showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   259
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   260
            if (moduleGraph.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   261
                throw new BadArgs("modules.xml must be specified").showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   262
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   263
            if (options.cmds == null || options.cmds.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   264
                warning("--commands is not set");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   265
            if (options.libs == null || options.libs.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   266
                warning("--libs is not set");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   267
            //if (options.configs == null || options.configs.isEmpty())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   268
            //    warning("--configs is not set");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   269
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   270
            // additional option combination validation
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   271
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   272
            boolean ok = run();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   273
            return ok ? EXIT_OK : EXIT_ERROR;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   274
        } catch (BadArgs e) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   275
            reportError(e.format, e.args);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   276
            if (e.showUsage)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   277
                log.println(USAGE_SUMMARY);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   278
            return EXIT_CMDERR;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   279
        } catch (Exception x) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   280
            x.printStackTrace();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   281
            return EXIT_ABNORMAL;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   282
        } finally {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   283
            log.flush();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   284
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   285
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   286
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   287
    private boolean run() throws IOException {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   288
        createImage();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   289
        return true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   290
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   291
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   292
    class SimpleResolver {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   293
        private final Set<Module> initialMods;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   294
        private final Map<String,Module> nameToModule = new HashMap<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   295
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   296
        SimpleResolver(Set<String> mods, Set<Module> graph) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   297
            graph.stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   298
                 .forEach(m -> nameToModule.put(m.name(), m));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   299
            initialMods = mods.stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   300
                         .map(this::nameToModule)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   301
                         .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   302
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   303
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   304
        /** Returns the transitive closure, in topological order */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   305
        List<String> resolve() {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   306
            List<Module> result = new LinkedList<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   307
            Set<Module> visited = new HashSet<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   308
            Set<Module> done = new HashSet<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   309
            for (Module m : initialMods) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   310
                if (!visited.contains(m))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   311
                    visit(m, visited, result, done);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   312
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   313
            return result.stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   314
                         .map(m -> m.name())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   315
                         .collect(Collectors.toList());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   316
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   317
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   318
        private void visit(Module m, Set<Module> visited,
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   319
                           List<Module> result, Set<Module> done) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   320
            if (visited.contains(m)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   321
                if (!done.contains(m))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   322
                    throw new IllegalArgumentException("Cyclic detected: " +
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   323
                            m + " " + getModuleDependences(m));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   324
                return;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   325
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   326
            visited.add(m);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   327
            getModuleDependences(m).stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   328
                                   .forEach(d -> visit(d, visited, result, done));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   329
            done.add(m);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   330
            result.add(m);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   331
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   332
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   333
        private Module nameToModule(String name) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   334
            Module m = nameToModule.get(name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   335
            if (m == null)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   336
                throw new RuntimeException("No module definition for " + name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   337
            return m;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   338
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   339
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   340
        private Set<Module> getModuleDependences(Module m) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   341
            return m.requires().stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   342
                    .map(d -> d.name())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   343
                    .map(this::nameToModule)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   344
                    .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   345
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   346
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   347
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   348
    private List<String> resolve(Set<String> mods ) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   349
        return (new SimpleResolver(mods, moduleGraph)).resolve();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   350
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   351
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   352
    /**
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   353
     * chmod ugo+x file
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   354
     */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   355
    private void setExecutable(Path file) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   356
        try {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   357
            Set<PosixFilePermission> perms = Files.getPosixFilePermissions(file);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   358
            perms.add(PosixFilePermission.OWNER_EXECUTE);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   359
            perms.add(PosixFilePermission.GROUP_EXECUTE);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   360
            perms.add(PosixFilePermission.OTHERS_EXECUTE);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   361
            Files.setPosixFilePermissions(file, perms);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   362
        } catch (IOException ioe) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   363
            throw new UncheckedIOException(ioe);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   364
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   365
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   366
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   367
    private void createImage() throws IOException {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   368
        Collection<String> modules = resolve(options.mods);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   369
        log.print(modules.stream().collect(Collectors.joining(" ")));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   370
        ImageFileHelper imageHelper = new ImageFileHelper(modules);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   371
        imageHelper.createModularImage(options.output);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   372
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   373
        // jspawnhelper, might be in lib or lib/ARCH
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   374
        Path jspawnhelper = Paths.get("jspawnhelper");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   375
        Path lib = options.output.resolve("lib");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   376
        Optional<Path> helper = Files.walk(lib, 2)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   377
                                     .filter(f -> f.getFileName().equals(jspawnhelper))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   378
                                     .findFirst();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   379
        if (helper.isPresent())
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   380
            setExecutable(helper.get());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   381
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   382
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   383
    private class ImageFileHelper {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   384
        final Collection<String> modules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   385
        final Set<String> bootModules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   386
        final Set<String> extModules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   387
        final Set<String> appModules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   388
        final ImageModules imf;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   389
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   390
        ImageFileHelper(Collection<String> modules) throws IOException {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   391
            this.modules = modules;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   392
            this.bootModules = modulesFor(BOOT_MODULES).stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   393
                     .filter(modules::contains)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   394
                     .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   395
            this.extModules = modulesFor(EXT_MODULES).stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   396
                    .filter(modules::contains)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   397
                    .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   398
            this.appModules = modules.stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   399
                    .filter(m -> !bootModules.contains(m) && !extModules.contains(m))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   400
                    .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   401
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   402
            this.imf = new ImageModules(bootModules, extModules, appModules);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   403
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   404
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   405
        void createModularImage(Path output) throws IOException {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   406
            Set<Archive> archives = modules.stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   407
                                            .map(this::toModuleArchive)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   408
                                            .collect(Collectors.toSet());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   409
            ImageFile.create(output, archives, imf, options.endian);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   410
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   411
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   412
        ModuleArchive toModuleArchive(String mn) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   413
            return new ModuleArchive(mn,
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   414
                                     moduleToPath(mn, options.classes, false/*true*/),
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   415
                                     moduleToPath(mn, options.cmds, false),
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   416
                                     moduleToPath(mn, options.libs, false),
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   417
                                     moduleToPath(mn, options.configs, false));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   418
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   419
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   420
        private Path moduleToPath(String name, List<Path> paths, boolean expect) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   421
            Set<Path> foundPaths = new HashSet<>();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   422
            if (paths != null) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   423
                for (Path p : paths) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   424
                    Path rp = p.resolve(name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   425
                    if (Files.exists(rp))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   426
                        foundPaths.add(rp);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   427
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   428
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   429
            if (foundPaths.size() > 1)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   430
                throw new RuntimeException("Found more that one path for " + name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   431
            if (expect && foundPaths.size() != 1)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   432
                throw new RuntimeException("Expected to find classes path for " + name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   433
            return foundPaths.size() == 0 ? null : foundPaths.iterator().next();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   434
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   435
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   436
        private List<String> modulesFor(String name) throws IOException {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   437
            try (InputStream is = ImageBuilder.class.getResourceAsStream(name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   438
                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   439
                return reader.lines().collect(Collectors.toList());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   440
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   441
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   442
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   443
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   444
    public void handleOptions(String[] args) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   445
        // process options
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   446
        for (int i=0; i < args.length; i++) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   447
            if (args[i].charAt(0) == '-') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   448
                String name = args[i];
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   449
                Option option = getOption(name);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   450
                String param = null;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   451
                if (option.hasArg) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   452
                    if (name.startsWith("--") && name.indexOf('=') > 0) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   453
                        param = name.substring(name.indexOf('=') + 1, name.length());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   454
                    } else if (i + 1 < args.length) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   455
                        param = args[++i];
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   456
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   457
                    if (param == null || param.isEmpty() || param.charAt(0) == '-') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   458
                        throw new BadArgs("Missing arg for %n", name).showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   459
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   460
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   461
                option.process(this, name, param);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   462
                if (option.ignoreRest()) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   463
                    i = args.length;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   464
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   465
            } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   466
                // process rest of the input arguments
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   467
                Path p = Paths.get(args[i]);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   468
                try {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   469
                    moduleGraph.addAll(ModulesXmlReader.readModules(p)
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   470
                            .stream()
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   471
                            .collect(Collectors.toSet()));
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   472
                } catch (Exception e) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   473
                    throw new RuntimeException(e);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   474
                }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   475
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   476
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   477
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   478
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   479
    private Option getOption(String name) throws BadArgs {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   480
        for (Option o : recognizedOptions) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   481
            if (o.matches(name)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   482
                return o;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   483
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   484
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   485
        throw new BadArgs("Unknown option %s", name).showUsage(true);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   486
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   487
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   488
    private void reportError(String format, Object... args) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   489
        log.format("Error: " + format + "%n", args);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   490
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   491
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   492
    private void warning(String format, Object... args) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   493
        log.format("Warning: " + format + "%n", args);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   494
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   495
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   496
    private static final String USAGE =
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   497
            "ImageBuilder <options> --output <path> path-to-modules-xml\n";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   498
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   499
    private static final String USAGE_SUMMARY =
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   500
            USAGE + "Use --help for a list of possible options.";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   501
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   502
    private void showHelp() {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   503
        log.format(USAGE);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   504
        log.format("Possible options are:%n");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   505
        for (Option o : recognizedOptions) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   506
            String name = o.aliases[0].substring(1); // there must always be at least one name
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   507
            name = name.charAt(0) == '-' ? name.substring(1) : name;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   508
            if (o.isHidden() || name.equals("h"))
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   509
                continue;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   510
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   511
            log.format("  --%s\t\t\t%s%n", name, o.description());
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   512
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   513
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   514
}