src/java.base/share/classes/jdk/internal/module/ModulePath.java
author redestad
Thu, 13 Dec 2018 15:31:05 +0100
changeset 53018 8bf9268df0e2
parent 51327 a19fda433921
permissions -rw-r--r--
8215281: Use String.isEmpty() when applicable in java.base Reviewed-by: dfuchs, alanb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     1
/*
49285
4d2e3f5abb48 8194746: (fs) Add equivalents of Paths.get to Path interface
bpb
parents: 47987
diff changeset
     2
 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     4
 *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    10
 *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    15
 * accompanied this code).
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    16
 *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    20
 *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    23
 * questions.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    24
 */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    25
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    26
package jdk.internal.module;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    27
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    28
import java.io.BufferedInputStream;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    29
import java.io.BufferedReader;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    30
import java.io.File;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    31
import java.io.IOException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    32
import java.io.InputStream;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    33
import java.io.InputStreamReader;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    34
import java.io.UncheckedIOException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    35
import java.lang.module.FindException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    36
import java.lang.module.InvalidModuleDescriptorException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    37
import java.lang.module.ModuleDescriptor;
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
    38
import java.lang.module.ModuleDescriptor.Builder;
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    39
import java.lang.module.ModuleFinder;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    40
import java.lang.module.ModuleReference;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    41
import java.net.URI;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    42
import java.nio.file.DirectoryStream;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    43
import java.nio.file.Files;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    44
import java.nio.file.NoSuchFileException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    45
import java.nio.file.Path;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    46
import java.nio.file.attribute.BasicFileAttributes;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    47
import java.util.ArrayList;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    48
import java.util.HashMap;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    49
import java.util.List;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    50
import java.util.Map;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    51
import java.util.Objects;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    52
import java.util.Optional;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    53
import java.util.Set;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    54
import java.util.jar.Attributes;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    55
import java.util.jar.JarEntry;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    56
import java.util.jar.JarFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    57
import java.util.jar.Manifest;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    58
import java.util.regex.Matcher;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    59
import java.util.regex.Pattern;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    60
import java.util.stream.Collectors;
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
    61
import java.util.zip.ZipException;
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    62
import java.util.zip.ZipFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    63
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    64
import jdk.internal.jmod.JmodFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    65
import jdk.internal.jmod.JmodFile.Section;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    66
import jdk.internal.perf.PerfCounter;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    67
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    68
/**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    69
 * A {@code ModuleFinder} that locates modules on the file system by searching
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    70
 * a sequence of directories or packaged modules. The ModuleFinder can be
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    71
 * created to work in either the run-time or link-time phases. In both cases it
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    72
 * locates modular JAR and exploded modules. When created for link-time then it
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    73
 * additionally locates modules in JMOD files. The ModuleFinder can also
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    74
 * optionally patch any modules that it locates with a ModulePatcher.
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    75
 */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    76
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    77
public class ModulePath implements ModuleFinder {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    78
    private static final String MODULE_INFO = "module-info.class";
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    79
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    80
    // the version to use for multi-release modular JARs
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    81
    private final Runtime.Version releaseVersion;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    82
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    83
    // true for the link phase (supports modules packaged in JMOD format)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    84
    private final boolean isLinkPhase;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    85
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    86
    // for patching modules, can be null
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    87
    private final ModulePatcher patcher;
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    88
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    89
    // the entries on this module path
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    90
    private final Path[] entries;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    91
    private int next;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    92
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    93
    // map of module name to module reference map for modules already located
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    94
    private final Map<String, ModuleReference> cachedModules = new HashMap<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    95
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    96
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    97
    private ModulePath(Runtime.Version version,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    98
                       boolean isLinkPhase,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    99
                       ModulePatcher patcher,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   100
                       Path... entries) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   101
        this.releaseVersion = version;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   102
        this.isLinkPhase = isLinkPhase;
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   103
        this.patcher = patcher;
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   104
        this.entries = entries.clone();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   105
        for (Path entry : this.entries) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   106
            Objects.requireNonNull(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   107
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   108
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   109
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   110
    /**
47866
39db80b32b69 8191632: Typos in comments due to duplicating words
igerasim
parents: 47216
diff changeset
   111
     * Returns a ModuleFinder that locates modules on the file system by
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   112
     * searching a sequence of directories and/or packaged modules. The modules
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   113
     * may be patched by the given ModulePatcher.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   114
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   115
    public static ModuleFinder of(ModulePatcher patcher, Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   116
        return new ModulePath(JarFile.runtimeVersion(), false, patcher, entries);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   117
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   118
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   119
    /**
47866
39db80b32b69 8191632: Typos in comments due to duplicating words
igerasim
parents: 47216
diff changeset
   120
     * Returns a ModuleFinder that locates modules on the file system by
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   121
     * searching a sequence of directories and/or packaged modules.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   122
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   123
    public static ModuleFinder of(Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   124
        return of((ModulePatcher)null, entries);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   125
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   126
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   127
    /**
47866
39db80b32b69 8191632: Typos in comments due to duplicating words
igerasim
parents: 47216
diff changeset
   128
     * Returns a ModuleFinder that locates modules on the file system by
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   129
     * searching a sequence of directories and/or packaged modules.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   130
     *
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   131
     * @param version The release version to use for multi-release JAR files
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   132
     * @param isLinkPhase {@code true} if the link phase to locate JMOD files
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   133
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   134
    public static ModuleFinder of(Runtime.Version version,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   135
                                  boolean isLinkPhase,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   136
                                  Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   137
        return new ModulePath(version, isLinkPhase, null, entries);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   138
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   139
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   140
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   141
    @Override
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   142
    public Optional<ModuleReference> find(String name) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   143
        Objects.requireNonNull(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   144
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   145
        // try cached modules
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   146
        ModuleReference m = cachedModules.get(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   147
        if (m != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   148
            return Optional.of(m);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   149
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   150
        // the module may not have been encountered yet
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   151
        while (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   152
            scanNextEntry();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   153
            m = cachedModules.get(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   154
            if (m != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   155
                return Optional.of(m);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   156
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   157
        return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   158
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   159
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   160
    @Override
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   161
    public Set<ModuleReference> findAll() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   162
        // need to ensure that all entries have been scanned
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   163
        while (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   164
            scanNextEntry();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   165
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   166
        return cachedModules.values().stream().collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   167
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   168
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   169
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   170
     * Returns {@code true} if there are additional entries to scan
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   171
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   172
    private boolean hasNextEntry() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   173
        return next < entries.length;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   174
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   175
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   176
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   177
     * Scans the next entry on the module path. A no-op if all entries have
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   178
     * already been scanned.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   179
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   180
     * @throws FindException if an error occurs scanning the next entry
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   181
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   182
    private void scanNextEntry() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   183
        if (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   184
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   185
            long t0 = System.nanoTime();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   186
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   187
            Path entry = entries[next];
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   188
            Map<String, ModuleReference> modules = scan(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   189
            next++;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   190
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   191
            // update cache, ignoring duplicates
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   192
            int initialSize = cachedModules.size();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   193
            for (Map.Entry<String, ModuleReference> e : modules.entrySet()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   194
                cachedModules.putIfAbsent(e.getKey(), e.getValue());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   195
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   196
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   197
            // update counters
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   198
            int added = cachedModules.size() - initialSize;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   199
            moduleCount.add(added);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   200
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   201
            scanTime.addElapsedTimeFrom(t0);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   202
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   203
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   204
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   205
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   206
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   207
     * Scan the given module path entry. If the entry is a directory then it is
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   208
     * a directory of modules or an exploded module. If the entry is a regular
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   209
     * file then it is assumed to be a packaged module.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   210
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   211
     * @throws FindException if an error occurs scanning the entry
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   212
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   213
    private Map<String, ModuleReference> scan(Path entry) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   214
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   215
        BasicFileAttributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   216
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   217
            attrs = Files.readAttributes(entry, BasicFileAttributes.class);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   218
        } catch (NoSuchFileException e) {
51327
a19fda433921 8209003: Consolidate use of empty collections in java.lang.module
redestad
parents: 49285
diff changeset
   219
            return Map.of();
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   220
        } catch (IOException ioe) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   221
            throw new FindException(ioe);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   222
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   223
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   224
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   225
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   226
            if (attrs.isDirectory()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   227
                Path mi = entry.resolve(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   228
                if (!Files.exists(mi)) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   229
                    // assume a directory of modules
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   230
                    return scanDirectory(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   231
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   232
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   233
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   234
            // packaged or exploded module
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   235
            ModuleReference mref = readModule(entry, attrs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   236
            if (mref != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   237
                String name = mref.descriptor().name();
51327
a19fda433921 8209003: Consolidate use of empty collections in java.lang.module
redestad
parents: 49285
diff changeset
   238
                return Map.of(name, mref);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   239
            }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   240
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   241
            // not recognized
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   242
            String msg;
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   243
            if (!isLinkPhase && entry.toString().endsWith(".jmod")) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   244
                msg = "JMOD format not supported at execution time";
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   245
            } else {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   246
                msg = "Module format not recognized";
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   247
            }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   248
            throw new FindException(msg + ": " + entry);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   249
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   250
        } catch (IOException ioe) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   251
            throw new FindException(ioe);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   252
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   253
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   254
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   255
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   256
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   257
     * Scans the given directory for packaged or exploded modules.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   258
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   259
     * @return a map of module name to ModuleReference for the modules found
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   260
     *         in the directory
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   261
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   262
     * @throws IOException if an I/O error occurs
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   263
     * @throws FindException if an error occurs scanning the entry or the
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   264
     *         directory contains two or more modules with the same name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   265
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   266
    private Map<String, ModuleReference> scanDirectory(Path dir)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   267
        throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   268
    {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   269
        // The map of name -> mref of modules found in this directory.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   270
        Map<String, ModuleReference> nameToReference = new HashMap<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   271
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   272
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   273
            for (Path entry : stream) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   274
                BasicFileAttributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   275
                try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   276
                    attrs = Files.readAttributes(entry, BasicFileAttributes.class);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   277
                } catch (NoSuchFileException ignore) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   278
                    // file has been removed or moved, ignore for now
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   279
                    continue;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   280
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   281
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   282
                ModuleReference mref = readModule(entry, attrs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   283
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   284
                // module found
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   285
                if (mref != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   286
                    // can have at most one version of a module in the directory
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   287
                    String name = mref.descriptor().name();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   288
                    ModuleReference previous = nameToReference.put(name, mref);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   289
                    if (previous != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   290
                        String fn1 = fileName(mref);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   291
                        String fn2 = fileName(previous);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   292
                        throw new FindException("Two versions of module "
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   293
                                                 + name + " found in " + dir
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   294
                                                 + " (" + fn1 + " and " + fn2 + ")");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   295
                    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   296
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   297
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   298
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   299
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   300
        return nameToReference;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   301
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   302
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   303
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   304
    /**
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   305
     * Reads a packaged or exploded module, returning a {@code ModuleReference}
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   306
     * to the module. Returns {@code null} if the entry is not recognized.
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   307
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   308
     * @throws IOException if an I/O error occurs
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   309
     * @throws FindException if an error occurs parsing its module descriptor
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   310
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   311
    private ModuleReference readModule(Path entry, BasicFileAttributes attrs)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   312
        throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   313
    {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   314
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   315
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   316
            // exploded module
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   317
            if (attrs.isDirectory()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   318
                return readExplodedModule(entry); // may return null
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   319
            }
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   320
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   321
            // JAR or JMOD file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   322
            if (attrs.isRegularFile()) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   323
                String fn = entry.getFileName().toString();
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   324
                boolean isDefaultFileSystem = isDefaultFileSystem(entry);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   325
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   326
                // JAR file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   327
                if (fn.endsWith(".jar")) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   328
                    if (isDefaultFileSystem) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   329
                        return readJar(entry);
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   330
                    } else {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   331
                        // the JAR file is in a custom file system so
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   332
                        // need to copy it to the local file system
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   333
                        Path tmpdir = Files.createTempDirectory("mlib");
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   334
                        Path target = Files.copy(entry, tmpdir.resolve(fn));
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   335
                        return readJar(target);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   336
                    }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   337
                }
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   338
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   339
                // JMOD file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   340
                if (isDefaultFileSystem && isLinkPhase && fn.endsWith(".jmod")) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   341
                    return readJMod(entry);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   342
                }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   343
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   344
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   345
            return null;
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   346
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   347
        } catch (InvalidModuleDescriptorException e) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   348
            throw new FindException("Error reading module: " + entry, e);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   349
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   350
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   351
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   352
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   353
     * Returns a string with the file name of the module if possible.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   354
     * If the module location is not a file URI then return the URI
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   355
     * as a string.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   356
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   357
    private String fileName(ModuleReference mref) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   358
        URI uri = mref.location().orElse(null);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   359
        if (uri != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   360
            if (uri.getScheme().equalsIgnoreCase("file")) {
49285
4d2e3f5abb48 8194746: (fs) Add equivalents of Paths.get to Path interface
bpb
parents: 47987
diff changeset
   361
                Path file = Path.of(uri);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   362
                return file.getFileName().toString();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   363
            } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   364
                return uri.toString();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   365
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   366
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   367
            return "<unknown>";
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   368
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   369
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   370
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   371
    // -- JMOD files --
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   372
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   373
    private Set<String> jmodPackages(JmodFile jf) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   374
        return jf.stream()
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   375
            .filter(e -> e.section() == Section.CLASSES)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   376
            .map(JmodFile.Entry::name)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   377
            .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   378
            .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   379
            .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   380
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   381
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   382
    /**
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   383
     * Returns a {@code ModuleReference} to a module in JMOD file on the
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   384
     * file system.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   385
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   386
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   387
     * @throws InvalidModuleDescriptorException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   388
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   389
    private ModuleReference readJMod(Path file) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   390
        try (JmodFile jf = new JmodFile(file)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   391
            ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   392
            try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   393
                attrs  = ModuleInfo.read(in, () -> jmodPackages(jf));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   394
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   395
            return ModuleReferences.newJModModule(attrs, file);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   396
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   397
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   398
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   399
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   400
    // -- JAR files --
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   401
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   402
    private static final String SERVICES_PREFIX = "META-INF/services/";
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   403
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   404
    private static final Attributes.Name AUTOMATIC_MODULE_NAME
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   405
        = new Attributes.Name("Automatic-Module-Name");
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   406
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   407
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   408
     * Returns the service type corresponding to the name of a services
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   409
     * configuration file if it is a legal type name.
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   410
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   411
     * For example, if called with "META-INF/services/p.S" then this method
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   412
     * returns a container with the value "p.S".
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   413
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   414
    private Optional<String> toServiceName(String cf) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   415
        assert cf.startsWith(SERVICES_PREFIX);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   416
        int index = cf.lastIndexOf("/") + 1;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   417
        if (index < cf.length()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   418
            String prefix = cf.substring(0, index);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   419
            if (prefix.equals(SERVICES_PREFIX)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   420
                String sn = cf.substring(index);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   421
                if (Checks.isClassName(sn))
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   422
                    return Optional.of(sn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   423
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   424
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   425
        return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   426
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   427
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   428
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   429
     * Reads the next line from the given reader and trims it of comments and
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   430
     * leading/trailing white space.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   431
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   432
     * Returns null if the reader is at EOF.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   433
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   434
    private String nextLine(BufferedReader reader) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   435
        String ln = reader.readLine();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   436
        if (ln != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   437
            int ci = ln.indexOf('#');
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   438
            if (ci >= 0)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   439
                ln = ln.substring(0, ci);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   440
            ln = ln.trim();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   441
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   442
        return ln;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   443
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   444
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   445
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   446
     * Treat the given JAR file as a module as follows:
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   447
     *
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   448
     * 1. The value of the Automatic-Module-Name attribute is the module name
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   449
     * 2. The version, and the module name when the  Automatic-Module-Name
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   450
     *    attribute is not present, is derived from the file ame of the JAR file
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   451
     * 3. All packages are derived from the .class files in the JAR file
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   452
     * 4. The contents of any META-INF/services configuration files are mapped
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   453
     *    to "provides" declarations
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   454
     * 5. The Main-Class attribute in the main attributes of the JAR manifest
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   455
     *    is mapped to the module descriptor mainClass if possible
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   456
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   457
    private ModuleDescriptor deriveModuleDescriptor(JarFile jf)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   458
        throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   459
    {
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   460
        // Read Automatic-Module-Name attribute if present
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   461
        Manifest man = jf.getManifest();
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   462
        Attributes attrs = null;
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   463
        String moduleName = null;
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   464
        if (man != null) {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   465
            attrs = man.getMainAttributes();
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   466
            if (attrs != null) {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   467
                moduleName = attrs.getValue(AUTOMATIC_MODULE_NAME);
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   468
            }
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   469
        }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   470
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   471
        // Derive the version, and the module name if needed, from JAR file name
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   472
        String fn = jf.getName();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   473
        int i = fn.lastIndexOf(File.separator);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   474
        if (i != -1)
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   475
            fn = fn.substring(i + 1);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   476
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   477
        // drop ".jar"
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   478
        String name = fn.substring(0, fn.length() - 4);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   479
        String vs = null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   480
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   481
        // find first occurrence of -${NUMBER}. or -${NUMBER}$
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   482
        Matcher matcher = Patterns.DASH_VERSION.matcher(name);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   483
        if (matcher.find()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   484
            int start = matcher.start();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   485
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   486
            // attempt to parse the tail as a version string
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   487
            try {
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   488
                String tail = name.substring(start + 1);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   489
                ModuleDescriptor.Version.parse(tail);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   490
                vs = tail;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   491
            } catch (IllegalArgumentException ignore) { }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   492
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   493
            name = name.substring(0, start);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   494
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   495
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   496
        // Create builder, using the name derived from file name when
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   497
        // Automatic-Module-Name not present
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   498
        Builder builder;
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   499
        if (moduleName != null) {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   500
            try {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   501
                builder = ModuleDescriptor.newAutomaticModule(moduleName);
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   502
            } catch (IllegalArgumentException e) {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   503
                throw new FindException(AUTOMATIC_MODULE_NAME + ": " + e.getMessage());
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   504
            }
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   505
        } else {
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   506
            builder = ModuleDescriptor.newAutomaticModule(cleanModuleName(name));
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   507
        }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   508
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   509
        // module version if present
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   510
        if (vs != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   511
            builder.version(vs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   512
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   513
        // scan the names of the entries in the JAR file
47987
85ea7e83af30 8189611: JarFile versioned stream and real name support
sherman
parents: 47866
diff changeset
   514
        Map<Boolean, Set<String>> map = jf.versionedStream()
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   515
                .filter(e -> !e.isDirectory())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   516
                .map(JarEntry::getName)
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   517
                .filter(e -> (e.endsWith(".class") ^ e.startsWith(SERVICES_PREFIX)))
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   518
                .collect(Collectors.partitioningBy(e -> e.startsWith(SERVICES_PREFIX),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   519
                                                   Collectors.toSet()));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   520
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   521
        Set<String> classFiles = map.get(Boolean.FALSE);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   522
        Set<String> configFiles = map.get(Boolean.TRUE);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   523
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   524
        // the packages containing class files
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   525
        Set<String> packages = classFiles.stream()
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   526
                .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   527
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   528
                .distinct()
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   529
                .collect(Collectors.toSet());
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   530
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   531
        // all packages are exported and open
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   532
        builder.packages(packages);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   533
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   534
        // map names of service configuration files to service names
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   535
        Set<String> serviceNames = configFiles.stream()
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   536
                .map(this::toServiceName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   537
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   538
                .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   539
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   540
        // parse each service configuration file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   541
        for (String sn : serviceNames) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   542
            JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   543
            List<String> providerClasses = new ArrayList<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   544
            try (InputStream in = jf.getInputStream(entry)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   545
                BufferedReader reader
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   546
                    = new BufferedReader(new InputStreamReader(in, "UTF-8"));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   547
                String cn;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   548
                while ((cn = nextLine(reader)) != null) {
53018
8bf9268df0e2 8215281: Use String.isEmpty() when applicable in java.base
redestad
parents: 51327
diff changeset
   549
                    if (!cn.isEmpty()) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   550
                        String pn = packageName(cn);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   551
                        if (!packages.contains(pn)) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   552
                            String msg = "Provider class " + cn + " not in module";
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   553
                            throw new InvalidModuleDescriptorException(msg);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   554
                        }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   555
                        providerClasses.add(cn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   556
                    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   557
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   558
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   559
            if (!providerClasses.isEmpty())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   560
                builder.provides(sn, providerClasses);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   561
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   562
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   563
        // Main-Class attribute if it exists
45652
33342314ce89 8181087: Module system implementation refresh (6/2017)
alanb
parents: 45004
diff changeset
   564
        if (attrs != null) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   565
            String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   566
            if (mainClass != null) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   567
                mainClass = mainClass.replace("/", ".");
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   568
                if (Checks.isClassName(mainClass)) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   569
                    String pn = packageName(mainClass);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   570
                    if (packages.contains(pn)) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   571
                        builder.mainClass(mainClass);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   572
                    }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   573
                }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   574
            }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   575
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   576
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   577
        return builder.build();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   578
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   579
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   580
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   581
     * Patterns used to derive the module name from a JAR file name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   582
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   583
    private static class Patterns {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   584
        static final Pattern DASH_VERSION = Pattern.compile("-(\\d+(\\.|$))");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   585
        static final Pattern NON_ALPHANUM = Pattern.compile("[^A-Za-z0-9]");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   586
        static final Pattern REPEATING_DOTS = Pattern.compile("(\\.)(\\1)+");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   587
        static final Pattern LEADING_DOTS = Pattern.compile("^\\.");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   588
        static final Pattern TRAILING_DOTS = Pattern.compile("\\.$");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   589
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   590
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   591
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   592
     * Clean up candidate module name derived from a JAR file name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   593
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   594
    private static String cleanModuleName(String mn) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   595
        // replace non-alphanumeric
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   596
        mn = Patterns.NON_ALPHANUM.matcher(mn).replaceAll(".");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   597
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   598
        // collapse repeating dots
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   599
        mn = Patterns.REPEATING_DOTS.matcher(mn).replaceAll(".");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   600
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   601
        // drop leading dots
53018
8bf9268df0e2 8215281: Use String.isEmpty() when applicable in java.base
redestad
parents: 51327
diff changeset
   602
        if (!mn.isEmpty() && mn.charAt(0) == '.')
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   603
            mn = Patterns.LEADING_DOTS.matcher(mn).replaceAll("");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   604
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   605
        // drop trailing dots
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   606
        int len = mn.length();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   607
        if (len > 0 && mn.charAt(len-1) == '.')
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   608
            mn = Patterns.TRAILING_DOTS.matcher(mn).replaceAll("");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   609
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   610
        return mn;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   611
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   612
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   613
    private Set<String> jarPackages(JarFile jf) {
47987
85ea7e83af30 8189611: JarFile versioned stream and real name support
sherman
parents: 47866
diff changeset
   614
        return jf.versionedStream()
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   615
                .filter(e -> !e.isDirectory())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   616
                .map(JarEntry::getName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   617
                .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   618
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   619
                .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   620
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   621
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   622
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   623
     * Returns a {@code ModuleReference} to a module in modular JAR file on
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   624
     * the file system.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   625
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   626
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   627
     * @throws FindException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   628
     * @throws InvalidModuleDescriptorException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   629
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   630
    private ModuleReference readJar(Path file) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   631
        try (JarFile jf = new JarFile(file.toFile(),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   632
                                      true,               // verify
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   633
                                      ZipFile.OPEN_READ,
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   634
                                      releaseVersion))
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   635
        {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   636
            ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   637
            JarEntry entry = jf.getJarEntry(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   638
            if (entry == null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   639
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   640
                // no module-info.class so treat it as automatic module
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   641
                try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   642
                    ModuleDescriptor md = deriveModuleDescriptor(jf);
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   643
                    attrs = new ModuleInfo.Attributes(md, null, null, null);
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   644
                } catch (RuntimeException e) {
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   645
                    throw new FindException("Unable to derive module descriptor for "
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   646
                                            + jf.getName(), e);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   647
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   648
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   649
            } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   650
                attrs = ModuleInfo.read(jf.getInputStream(entry),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   651
                                        () -> jarPackages(jf));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   652
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   653
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   654
            return ModuleReferences.newJarModule(attrs, patcher, file);
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   655
        } catch (ZipException e) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   656
            throw new FindException("Error reading " + file, e);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   657
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   658
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   659
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   660
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   661
    // -- exploded directories --
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   662
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   663
    private Set<String> explodedPackages(Path dir) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   664
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   665
            return Files.find(dir, Integer.MAX_VALUE,
44545
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   666
                    ((path, attrs) -> attrs.isRegularFile() && !isHidden(path)))
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   667
                    .map(path -> dir.relativize(path))
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   668
                    .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   669
                    .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   670
                    .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   671
        } catch (IOException x) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   672
            throw new UncheckedIOException(x);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   673
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   674
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   675
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   676
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   677
     * Returns a {@code ModuleReference} to an exploded module on the file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   678
     * system or {@code null} if {@code module-info.class} not found.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   679
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   680
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   681
     * @throws InvalidModuleDescriptorException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   682
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   683
    private ModuleReference readExplodedModule(Path dir) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   684
        Path mi = dir.resolve(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   685
        ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   686
        try (InputStream in = Files.newInputStream(mi)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   687
            attrs = ModuleInfo.read(new BufferedInputStream(in),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   688
                                    () -> explodedPackages(dir));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   689
        } catch (NoSuchFileException e) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   690
            // for now
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   691
            return null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   692
        }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   693
        return ModuleReferences.newExplodedModule(attrs, patcher, dir);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   694
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   695
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   696
    /**
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   697
     * Maps a type name to its package name.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   698
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   699
    private static String packageName(String cn) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   700
        int index = cn.lastIndexOf('.');
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   701
        return (index == -1) ? "" : cn.substring(0, index);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   702
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   704
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   705
     * Maps the name of an entry in a JAR or ZIP file to a package name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   706
     *
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   707
     * @throws InvalidModuleDescriptorException if the name is a class file in
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   708
     *         the top-level directory of the JAR/ZIP file (and it's not
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   709
     *         module-info.class)
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   710
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   711
    private Optional<String> toPackageName(String name) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   712
        assert !name.endsWith("/");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   713
        int index = name.lastIndexOf("/");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   714
        if (index == -1) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   715
            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   716
                String msg = name + " found in top-level directory"
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   717
                             + " (unnamed package not allowed in module)";
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   718
                throw new InvalidModuleDescriptorException(msg);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   719
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   720
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   721
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   722
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   723
        String pn = name.substring(0, index).replace('/', '.');
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   724
        if (Checks.isPackageName(pn)) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   725
            return Optional.of(pn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   726
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   727
            // not a valid package name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   728
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   729
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   730
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   731
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   732
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   733
     * Maps the relative path of an entry in an exploded module to a package
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   734
     * name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   735
     *
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   736
     * @throws InvalidModuleDescriptorException if the name is a class file in
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   737
     *         the top-level directory (and it's not module-info.class)
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   738
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   739
    private Optional<String> toPackageName(Path file) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   740
        assert file.getRoot() == null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   741
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   742
        Path parent = file.getParent();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   743
        if (parent == null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   744
            String name = file.toString();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   745
            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   746
                String msg = name + " found in top-level directory"
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   747
                             + " (unnamed package not allowed in module)";
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   748
                throw new InvalidModuleDescriptorException(msg);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   749
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   750
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   751
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   752
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   753
        String pn = parent.toString().replace(File.separatorChar, '.');
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   754
        if (Checks.isPackageName(pn)) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   755
            return Optional.of(pn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   756
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   757
            // not a valid package name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   758
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   759
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   760
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   761
44545
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   762
    /**
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   763
     * Returns true if the given file exists and is a hidden file
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   764
     */
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   765
    private boolean isHidden(Path file) {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   766
        try {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   767
            return Files.isHidden(file);
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   768
        } catch (IOException ioe) {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   769
            return false;
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   770
        }
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   771
    }
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   772
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   773
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   774
    /**
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   775
     * Return true if a path locates a path in the default file system
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   776
     */
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   777
    private boolean isDefaultFileSystem(Path path) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   778
        return path.getFileSystem().provider()
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   779
                .getScheme().equalsIgnoreCase("file");
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   780
    }
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   781
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   782
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   783
    private static final PerfCounter scanTime
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   784
        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.scanTime");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   785
    private static final PerfCounter moduleCount
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   786
        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.modules");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   787
}