jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
author alanb
Tue, 03 May 2016 09:09:57 +0100
changeset 37779 7c84df693837
parent 36674 7ab530dd6f10
child 40261 86a49ba76f52
permissions -rw-r--r--
8154956: Module system implementation refresh (4/2016) Reviewed-by: alanb, mchung, chegar, redestad Contributed-by: alan.bateman@oracle.com, mandy.chung@oracle.com, erik.joelsson@oracle.com, chris.hegarty@oracle.com, peter.levart@gmail.com, sundararajan.athijegannathan@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     1
/*
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     2
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     4
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    10
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    15
 * accompanied this code).
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    16
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    20
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    23
 * questions.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    24
 */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    25
package jdk.internal.module;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    26
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    27
import java.io.Closeable;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    28
import java.io.File;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    29
import java.io.IOError;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    30
import java.io.IOException;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    31
import java.io.InputStream;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    32
import java.io.UncheckedIOException;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    33
import java.lang.module.ModuleDescriptor;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    34
import java.lang.module.ModuleReader;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    35
import java.lang.module.ModuleReference;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    36
import java.net.MalformedURLException;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    37
import java.net.URI;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    38
import java.net.URL;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    39
import java.nio.ByteBuffer;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    40
import java.nio.file.Files;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    41
import java.nio.file.Path;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    42
import java.nio.file.Paths;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    43
import java.util.ArrayList;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    44
import java.util.Collections;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    45
import java.util.HashMap;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    46
import java.util.HashSet;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    47
import java.util.List;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    48
import java.util.Map;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    49
import java.util.Optional;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    50
import java.util.Set;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    51
import java.util.jar.JarEntry;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    52
import java.util.jar.JarFile;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    53
36674
7ab530dd6f10 8149122: Move sun.misc.URLClassPath and Resouce to an internal package
chegar
parents: 36511
diff changeset
    54
import jdk.internal.loader.Resource;
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    55
import jdk.internal.misc.JavaLangModuleAccess;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    56
import jdk.internal.misc.SharedSecrets;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    57
import sun.net.www.ParseUtil;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    58
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    59
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    60
/**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    61
 * Provides support for patching modules in the boot layer with -Xpatch.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    62
 */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    63
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    64
public final class ModulePatcher {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    65
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    66
    private static final JavaLangModuleAccess JLMA
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    67
        = SharedSecrets.getJavaLangModuleAccess();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    68
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    69
    // the prefix of the system properties that encode the value of -Xpatch
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    70
    private static final String PATCH_PROPERTY_PREFIX = "jdk.launcher.patch.";
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    71
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    72
    // module name -> sequence of patches (directories or JAR files)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    73
    private static final Map<String, List<Path>> PATCH_MAP = decodeProperties();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    74
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    75
    private ModulePatcher() { }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    76
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    77
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    78
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    79
     * Decodes the values of -Xpatch options, returning a Map of module name to
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    80
     * list of file paths.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    81
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    82
     * @throws IllegalArgumentException if the the module name is missing or
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    83
     *         -Xpatch is used more than once to patch the same module
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    84
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    85
    private static Map<String, List<Path>> decodeProperties() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    86
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    87
        int index = 0;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    88
        String value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    89
        if (value == null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    90
            return Collections.emptyMap();  // -Xpatch not specified
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    91
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    92
        Map<String, List<Path>> map = new HashMap<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    93
        while (value != null) {
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
    94
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
    95
            // <module>=<file>(:<file>)*
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    96
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
    97
            int pos = value.indexOf('=');
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
    98
            if (pos == -1)
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
    99
                throwIAE("Unable to parse: " + value);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   100
            if (pos == 0)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   101
                throwIAE("Missing module name: " + value);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   102
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   103
            String mn = value.substring(0, pos);
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   104
            List<Path> list = map.get(mn);
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   105
            if (list != null)
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   106
                throwIAE("Module " + mn + " specified more than once");
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   107
            list = new ArrayList<>();
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   108
            map.put(mn, list);
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   109
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   110
            String paths = value.substring(pos+1);
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   111
            for (String path : paths.split(File.pathSeparator)) {
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   112
                if (!path.isEmpty()) {
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   113
                    list.add(Paths.get(path));
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   114
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   115
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   116
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   117
            index++;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   118
            value = System.getProperty(PATCH_PROPERTY_PREFIX + index);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   119
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   120
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   121
        return map;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   122
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   123
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   124
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   125
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   126
     * Returns a module reference that interposes on the given module if
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   127
     * needed. If there are no patches for the given module then the module
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   128
     * reference is simply returned. Otherwise the patches for the module
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   129
     * are scanned (to find any new concealed packages) and a new module
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   130
     * reference is returned.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   131
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   132
     * @throws UncheckedIOException if an I/O error is detected
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   133
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   134
    public static ModuleReference interposeIfNeeded(ModuleReference mref) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   135
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   136
        ModuleDescriptor descriptor = mref.descriptor();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   137
        String mn = descriptor.name();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   138
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   139
        // if there are no patches for the module then nothing to do
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   140
        List<Path> paths = PATCH_MAP.get(mn);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   141
        if (paths == null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   142
            return mref;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   143
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   144
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   145
        // scan the JAR file or directory tree to get the set of packages
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   146
        Set<String> packages = new HashSet<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   147
        try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   148
            for (Path file : paths) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   149
                if (Files.isRegularFile(file)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   150
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   151
                    // JAR file - do not open as a multi-release JAR as this
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   152
                    // is not supported by the boot class loader
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   153
                    try (JarFile jf = new JarFile(file.toFile())) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   154
                        jf.stream()
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   155
                          .filter(e -> e.getName().endsWith(".class"))
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   156
                          .map(e -> toPackageName(file, e))
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   157
                          .filter(pn -> pn.length() > 0)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   158
                          .forEach(packages::add);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   159
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   160
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   161
                } else if (Files.isDirectory(file)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   162
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   163
                    // exploded directory
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   164
                    Path top = file;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   165
                    Files.find(top, Integer.MAX_VALUE,
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   166
                            ((path, attrs) -> attrs.isRegularFile() &&
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   167
                                    path.toString().endsWith(".class")))
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   168
                            .map(path -> toPackageName(top, path))
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   169
                            .filter(pn -> pn.length() > 0)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   170
                            .forEach(packages::add);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   171
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   172
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   173
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   174
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   175
        } catch (IOException ioe) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   176
            throw new UncheckedIOException(ioe);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   177
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   178
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   179
        // if there are new packages then we need a new ModuleDescriptor
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   180
        Set<String> original = descriptor.packages();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   181
        packages.addAll(original);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   182
        if (packages.size() > original.size()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   183
            descriptor = JLMA.newModuleDescriptor(descriptor, packages);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   184
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   185
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   186
        // return a module reference to the patched module
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   187
        URI location = mref.location().orElse(null);
37779
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   188
        return JLMA.newPatchedModule(descriptor,
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   189
                                     location,
7c84df693837 8154956: Module system implementation refresh (4/2016)
alanb
parents: 36674
diff changeset
   190
                                     () -> new PatchedModuleReader(paths, mref));
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   191
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   192
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   193
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   194
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   195
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   196
     * A ModuleReader that reads resources from a patched module.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   197
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   198
     * This class is public so as to expose the findResource method to the
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   199
     * built-in class loaders and avoid locating the resource twice during
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   200
     * class loading (once to locate the resource, the second to gets the
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   201
     * URL for the CodeSource).
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   202
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   203
    public static class PatchedModuleReader implements ModuleReader {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   204
        private final List<ResourceFinder> finders;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   205
        private final ModuleReference mref;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   206
        private final URL delegateCodeSourceURL;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   207
        private volatile ModuleReader delegate;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   208
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   209
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   210
         * Creates the ModuleReader to reads resources a patched module.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   211
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   212
        PatchedModuleReader(List<Path> patches, ModuleReference mref) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   213
            List<ResourceFinder> finders = new ArrayList<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   214
            boolean initialized = false;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   215
            try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   216
                for (Path file : patches) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   217
                    if (Files.isRegularFile(file)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   218
                        finders.add(new JarResourceFinder(file));
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   219
                    } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   220
                        finders.add(new ExplodedResourceFinder(file));
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   221
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   222
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   223
                initialized = true;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   224
            } catch (IOException ioe) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   225
                throw new UncheckedIOException(ioe);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   226
            } finally {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   227
                // close all ResourceFinder in the event of an error
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   228
                if (!initialized) closeAll(finders);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   229
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   230
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   231
            this.finders = finders;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   232
            this.mref = mref;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   233
            this.delegateCodeSourceURL = codeSourceURL(mref);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   234
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   235
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   236
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   237
         * Closes all resource finders.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   238
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   239
        private static void closeAll(List<ResourceFinder> finders) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   240
            for (ResourceFinder finder : finders) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   241
                try { finder.close(); } catch (IOException ioe) { }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   242
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   243
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   244
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   245
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   246
         * Returns the code source URL for the given module.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   247
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   248
        private static URL codeSourceURL(ModuleReference mref) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   249
            try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   250
                Optional<URI> ouri = mref.location();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   251
                if (ouri.isPresent())
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   252
                    return ouri.get().toURL();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   253
            } catch (MalformedURLException e) { }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   254
            return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   255
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   256
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   257
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   258
         * Returns the ModuleReader to delegate to when the resource is not
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   259
         * found in a patch location.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   260
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   261
        private ModuleReader delegate() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   262
            ModuleReader r = delegate;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   263
            if (r == null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   264
                synchronized (this) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   265
                    r = delegate;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   266
                    if (r == null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   267
                        delegate = r = mref.open();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   268
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   269
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   270
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   271
            return r;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   272
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   273
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   274
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   275
         * Finds a resources in the patch locations. Returns null if not found.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   276
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   277
        private Resource findResourceInPatch(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   278
            for (ResourceFinder finder : finders) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   279
                Resource r = finder.find(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   280
                if (r != null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   281
                    return r;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   282
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   283
            return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   284
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   285
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   286
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   287
         * Finds a resource of the given name in the patched module.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   288
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   289
        public Resource findResource(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   290
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   291
            // patch locations
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   292
            Resource r = findResourceInPatch(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   293
            if (r != null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   294
                return r;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   295
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   296
            // original module
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   297
            ByteBuffer bb = delegate().read(name).orElse(null);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   298
            if (bb == null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   299
                return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   300
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   301
            return new Resource() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   302
                private <T> T shouldNotGetHere(Class<T> type) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   303
                    throw new InternalError("should not get here");
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   304
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   305
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   306
                public String getName() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   307
                    return shouldNotGetHere(String.class);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   308
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   309
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   310
                public URL getURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   311
                    return shouldNotGetHere(URL.class);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   312
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   313
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   314
                public URL getCodeSourceURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   315
                    return delegateCodeSourceURL;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   316
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   317
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   318
                public ByteBuffer getByteBuffer() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   319
                    return bb;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   320
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   321
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   322
                public InputStream getInputStream() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   323
                    return shouldNotGetHere(InputStream.class);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   324
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   325
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   326
                public int getContentLength() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   327
                    return shouldNotGetHere(int.class);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   328
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   329
            };
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   330
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   331
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   332
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   333
        public Optional<URI> find(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   334
            Resource r = findResourceInPatch(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   335
            if (r != null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   336
                URI uri = URI.create(r.getURL().toString());
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   337
                return Optional.of(uri);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   338
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   339
                return delegate().find(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   340
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   341
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   342
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   343
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   344
        public Optional<InputStream> open(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   345
            Resource r = findResourceInPatch(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   346
            if (r != null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   347
                return Optional.of(r.getInputStream());
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   348
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   349
                return delegate().open(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   350
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   351
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   352
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   353
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   354
        public Optional<ByteBuffer> read(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   355
            Resource r = findResourceInPatch(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   356
            if (r != null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   357
                ByteBuffer bb = r.getByteBuffer();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   358
                assert !bb.isDirect();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   359
                return Optional.of(bb);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   360
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   361
                return delegate().read(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   362
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   363
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   364
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   365
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   366
        public void release(ByteBuffer bb) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   367
            if (bb.isDirect()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   368
                try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   369
                    delegate().release(bb);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   370
                } catch (IOException ioe) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   371
                    throw new InternalError(ioe);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   372
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   373
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   374
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   375
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   376
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   377
        public void close() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   378
            closeAll(finders);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   379
            delegate().close();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   380
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   381
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   382
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   383
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   384
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   385
     * A resource finder that find resources in a patch location.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   386
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   387
    private static interface ResourceFinder extends Closeable {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   388
        Resource find(String name) throws IOException;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   389
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   390
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   391
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   392
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   393
     * A ResourceFinder that finds resources in a JAR file.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   394
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   395
    private static class JarResourceFinder implements ResourceFinder {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   396
        private final JarFile jf;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   397
        private final URL csURL;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   398
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   399
        JarResourceFinder(Path path) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   400
            this.jf = new JarFile(path.toFile());
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   401
            this.csURL = path.toUri().toURL();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   402
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   403
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   404
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   405
        public void close() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   406
            jf.close();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   407
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   408
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   409
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   410
        public Resource find(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   411
            JarEntry entry = jf.getJarEntry(name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   412
            if (entry == null)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   413
                return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   414
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   415
            return new Resource() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   416
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   417
                public String getName() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   418
                    return name;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   419
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   420
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   421
                public URL getURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   422
                    String encodedPath = ParseUtil.encodePath(name, false);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   423
                    try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   424
                        return new URL("jar:" + csURL + "!/" + encodedPath);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   425
                    } catch (MalformedURLException e) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   426
                        return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   427
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   428
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   429
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   430
                public URL getCodeSourceURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   431
                    return csURL;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   432
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   433
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   434
                public ByteBuffer getByteBuffer() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   435
                    byte[] bytes = getInputStream().readAllBytes();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   436
                    return ByteBuffer.wrap(bytes);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   437
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   438
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   439
                public InputStream getInputStream() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   440
                    return jf.getInputStream(entry);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   441
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   442
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   443
                public int getContentLength() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   444
                    long size = entry.getSize();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   445
                    return (size > Integer.MAX_VALUE) ? -1 : (int) size;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   446
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   447
            };
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   448
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   449
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   450
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   451
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   452
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   453
     * A ResourceFinder that finds resources on the file system.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   454
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   455
    private static class ExplodedResourceFinder implements ResourceFinder {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   456
        private final Path dir;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   457
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   458
        ExplodedResourceFinder(Path dir) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   459
            this.dir = dir;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   460
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   461
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   462
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   463
        public void close() { }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   464
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   465
        @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   466
        public Resource find(String name) throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   467
            Path file = Paths.get(name.replace('/', File.separatorChar));
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   468
            if (file.getRoot() == null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   469
                file = dir.resolve(file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   470
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   471
                // drop the root component so that the resource is
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   472
                // located relative to the module directory
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   473
                int n = file.getNameCount();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   474
                if (n == 0)
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   475
                    return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   476
                file = dir.resolve(file.subpath(0, n));
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   477
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   478
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   479
            if (Files.isRegularFile(file)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   480
                return newResource(name, dir, file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   481
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   482
                return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   483
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   484
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   485
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   486
        private Resource newResource(String name, Path top, Path file) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   487
            return new Resource() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   488
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   489
                public String getName() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   490
                    return name;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   491
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   492
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   493
                public URL getURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   494
                    try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   495
                        return file.toUri().toURL();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   496
                    } catch (IOException | IOError e) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   497
                        return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   498
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   499
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   500
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   501
                public URL getCodeSourceURL() {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   502
                    try {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   503
                        return top.toUri().toURL();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   504
                    } catch (IOException | IOError e) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   505
                        return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   506
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   507
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   508
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   509
                public ByteBuffer getByteBuffer() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   510
                    return ByteBuffer.wrap(Files.readAllBytes(file));
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   511
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   512
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   513
                public InputStream getInputStream() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   514
                    return Files.newInputStream(file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   515
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   516
                @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   517
                public int getContentLength() throws IOException {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   518
                    long size = Files.size(file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   519
                    return (size > Integer.MAX_VALUE) ? -1 : (int)size;
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   520
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   521
            };
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   522
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   523
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   524
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   525
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   526
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   527
     * Derives a package name from a file path to a .class file.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   528
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   529
    private static String toPackageName(Path top, Path file) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   530
        Path entry = top.relativize(file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   531
        Path parent = entry.getParent();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   532
        if (parent == null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   533
            return warnUnnamedPackage(top, entry.toString());
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   534
        } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   535
            return parent.toString().replace(File.separatorChar, '.');
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   536
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   537
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   538
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   539
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   540
     * Derives a package name from the name of an entry in a JAR file.
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   541
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   542
    private static String toPackageName(Path file, JarEntry entry) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   543
        String name = entry.getName();
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   544
        int index = name.lastIndexOf("/");
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   545
        if (index == -1) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   546
            return warnUnnamedPackage(file, name);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   547
        } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   548
            return name.substring(0, index).replace('/', '.');
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   549
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   550
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   551
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   552
    private static String warnUnnamedPackage(Path file, String e) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   553
        System.err.println("WARNING: " + e + " not allowed in patch: " + file);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   554
        return "";
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   555
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   556
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   557
    private static void throwIAE(String msg) {
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   558
        throw new IllegalArgumentException(msg);
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   559
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents:
diff changeset
   560
36674
7ab530dd6f10 8149122: Move sun.misc.URLClassPath and Resouce to an internal package
chegar
parents: 36511
diff changeset
   561
}