jdk/src/java.base/share/classes/jdk/internal/module/ModulePath.java
author alanb
Thu, 04 May 2017 07:26:55 +0000
changeset 45004 ea3137042a61
parent 44545 83b611b88ac8
child 45652 33342314ce89
permissions -rw-r--r--
8178380: Module system implementation refresh (5/2017) Reviewed-by: mchung, alanb, sspitsyn Contributed-by: alan.bateman@oracle.com, mandy.chung@oracle.com, chris.hegarty@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
     1
/*
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
     2
 * Copyright (c) 2014, 2017, 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;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    38
import java.lang.module.ModuleFinder;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    39
import java.lang.module.ModuleReference;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    40
import java.net.URI;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    41
import java.nio.file.DirectoryStream;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    42
import java.nio.file.Files;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    43
import java.nio.file.NoSuchFileException;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    44
import java.nio.file.Path;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    45
import java.nio.file.Paths;
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.Collections;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    49
import java.util.HashMap;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    50
import java.util.List;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    51
import java.util.Map;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    52
import java.util.Objects;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    53
import java.util.Optional;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    54
import java.util.Set;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    55
import java.util.jar.Attributes;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    56
import java.util.jar.JarEntry;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    57
import java.util.jar.JarFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    58
import java.util.jar.Manifest;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    59
import java.util.regex.Matcher;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    60
import java.util.regex.Pattern;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    61
import java.util.stream.Collectors;
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
    62
import java.util.zip.ZipException;
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    63
import java.util.zip.ZipFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    64
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    65
import jdk.internal.jmod.JmodFile;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    66
import jdk.internal.jmod.JmodFile.Section;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    67
import jdk.internal.perf.PerfCounter;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    68
import jdk.internal.util.jar.VersionedStream;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    69
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    70
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    71
/**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    72
 * 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
    73
 * a sequence of directories or packaged modules. The ModuleFinder can be
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    74
 * 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
    75
 * 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
    76
 * additionally locates modules in JMOD files. The ModuleFinder can also
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    77
 * optionally patch any modules that it locates with a ModulePatcher.
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    78
 */
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
public class ModulePath implements ModuleFinder {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    81
    private static final String MODULE_INFO = "module-info.class";
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
    // the version to use for multi-release modular JARs
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    84
    private final Runtime.Version releaseVersion;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    85
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    86
    // true for the link phase (supports modules packaged in JMOD format)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    87
    private final boolean isLinkPhase;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    88
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    89
    // for patching modules, can be null
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    90
    private final ModulePatcher patcher;
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    91
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    92
    // the entries on this module path
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    93
    private final Path[] entries;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    94
    private int next;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    95
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    96
    // map of module name to module reference map for modules already located
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    97
    private final Map<String, ModuleReference> cachedModules = new HashMap<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
    98
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
    99
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   100
    private ModulePath(Runtime.Version version,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   101
                       boolean isLinkPhase,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   102
                       ModulePatcher patcher,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   103
                       Path... entries) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   104
        this.releaseVersion = version;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   105
        this.isLinkPhase = isLinkPhase;
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   106
        this.patcher = patcher;
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   107
        this.entries = entries.clone();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   108
        for (Path entry : this.entries) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   109
            Objects.requireNonNull(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   110
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   111
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   112
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   113
    /**
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   114
     * Returns a ModuleFinder that that locates modules on the file system by
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   115
     * searching a sequence of directories and/or packaged modules. The modules
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   116
     * may be patched by the given ModulePatcher.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   117
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   118
    public static ModuleFinder of(ModulePatcher patcher, Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   119
        return new ModulePath(JarFile.runtimeVersion(), false, patcher, entries);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   120
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   121
43712
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
     * Returns a ModuleFinder that that locates modules on the file system by
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   124
     * searching a sequence of directories and/or packaged modules.
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
    public static ModuleFinder of(Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   127
        return of((ModulePatcher)null, entries);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   128
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   129
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
     * Returns a ModuleFinder that that locates modules on the file system by
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   132
     * searching a sequence of directories and/or packaged modules.
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
     * @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
   135
     * @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
   136
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   137
    public static ModuleFinder of(Runtime.Version version,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   138
                                  boolean isLinkPhase,
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   139
                                  Path... entries) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   140
        return new ModulePath(version, isLinkPhase, null, entries);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   141
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   142
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   143
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   144
    @Override
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   145
    public Optional<ModuleReference> find(String name) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   146
        Objects.requireNonNull(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   147
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   148
        // try cached modules
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   149
        ModuleReference m = cachedModules.get(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   150
        if (m != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   151
            return Optional.of(m);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   152
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   153
        // the module may not have been encountered yet
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   154
        while (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   155
            scanNextEntry();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   156
            m = cachedModules.get(name);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   157
            if (m != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   158
                return Optional.of(m);
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
        return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   161
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   162
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   163
    @Override
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   164
    public Set<ModuleReference> findAll() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   165
        // need to ensure that all entries have been scanned
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   166
        while (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   167
            scanNextEntry();
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
        return cachedModules.values().stream().collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   170
    }
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
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   173
     * Returns {@code true} if there are additional entries to scan
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
    private boolean hasNextEntry() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   176
        return next < entries.length;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   177
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   178
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
     * 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
   181
     * already been scanned.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   182
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   183
     * @throws FindException if an error occurs scanning the next entry
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
    private void scanNextEntry() {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   186
        if (hasNextEntry()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   187
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   188
            long t0 = System.nanoTime();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   189
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   190
            Path entry = entries[next];
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   191
            Map<String, ModuleReference> modules = scan(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   192
            next++;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   193
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   194
            // update cache, ignoring duplicates
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   195
            int initialSize = cachedModules.size();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   196
            for (Map.Entry<String, ModuleReference> e : modules.entrySet()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   197
                cachedModules.putIfAbsent(e.getKey(), e.getValue());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   198
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   199
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   200
            // update counters
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   201
            int added = cachedModules.size() - initialSize;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   202
            moduleCount.add(added);
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
            scanTime.addElapsedTimeFrom(t0);
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   208
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   209
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   210
     * 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
   211
     * 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
   212
     * file then it is assumed to be a packaged module.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   213
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   214
     * @throws FindException if an error occurs scanning the entry
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   215
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   216
    private Map<String, ModuleReference> scan(Path entry) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   217
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   218
        BasicFileAttributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   219
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   220
            attrs = Files.readAttributes(entry, BasicFileAttributes.class);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   221
        } catch (NoSuchFileException e) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   222
            return Collections.emptyMap();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   223
        } catch (IOException ioe) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   224
            throw new FindException(ioe);
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   227
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   228
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   229
            if (attrs.isDirectory()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   230
                Path mi = entry.resolve(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   231
                if (!Files.exists(mi)) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   232
                    // assume a directory of modules
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   233
                    return scanDirectory(entry);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   234
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   235
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   236
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   237
            // packaged or exploded module
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   238
            ModuleReference mref = readModule(entry, attrs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   239
            if (mref != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   240
                String name = mref.descriptor().name();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   241
                return Collections.singletonMap(name, mref);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   242
            }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   243
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   244
            // not recognized
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   245
            String msg;
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   246
            if (!isLinkPhase && entry.toString().endsWith(".jmod")) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   247
                msg = "JMOD format not supported at execution time";
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   248
            } else {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   249
                msg = "Module format not recognized";
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   250
            }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   251
            throw new FindException(msg + ": " + entry);
42703
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
        } catch (IOException ioe) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   254
            throw new FindException(ioe);
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
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
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   260
     * Scans the given directory for packaged or exploded modules.
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
     * @return a map of module name to ModuleReference for the modules found
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   263
     *         in the directory
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   264
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   265
     * @throws IOException if an I/O error occurs
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   266
     * @throws FindException if an error occurs scanning the entry or the
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   267
     *         directory contains two or more modules with the same name
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
    private Map<String, ModuleReference> scanDirectory(Path dir)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   270
        throws IOException
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
        // The map of name -> mref of modules found in this directory.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   273
        Map<String, ModuleReference> nameToReference = new HashMap<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   274
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   275
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   276
            for (Path entry : stream) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   277
                BasicFileAttributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   278
                try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   279
                    attrs = Files.readAttributes(entry, BasicFileAttributes.class);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   280
                } catch (NoSuchFileException ignore) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   281
                    // file has been removed or moved, ignore for now
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   282
                    continue;
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   285
                ModuleReference mref = readModule(entry, attrs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   286
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   287
                // module found
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   288
                if (mref != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   289
                    // can have at most one version of a module in the directory
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   290
                    String name = mref.descriptor().name();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   291
                    ModuleReference previous = nameToReference.put(name, mref);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   292
                    if (previous != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   293
                        String fn1 = fileName(mref);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   294
                        String fn2 = fileName(previous);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   295
                        throw new FindException("Two versions of module "
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   296
                                                 + name + " found in " + dir
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   297
                                                 + " (" + fn1 + " and " + fn2 + ")");
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
            }
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
        return nameToReference;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   304
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   305
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   306
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   307
    /**
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   308
     * Reads a packaged or exploded module, returning a {@code ModuleReference}
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   309
     * 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
   310
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   311
     * @throws IOException if an I/O error occurs
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   312
     * @throws FindException if an error occurs parsing its module descriptor
42703
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
    private ModuleReference readModule(Path entry, BasicFileAttributes attrs)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   315
        throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   316
    {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   317
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   318
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   319
            // exploded module
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   320
            if (attrs.isDirectory()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   321
                return readExplodedModule(entry); // may return null
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   322
            }
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   323
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   324
            // JAR or JMOD file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   325
            if (attrs.isRegularFile()) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   326
                String fn = entry.getFileName().toString();
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   327
                boolean isDefaultFileSystem = isDefaultFileSystem(entry);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   328
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   329
                // JAR file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   330
                if (fn.endsWith(".jar")) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   331
                    if (isDefaultFileSystem) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   332
                        return readJar(entry);
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   333
                    } else {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   334
                        // the JAR file is in a custom file system so
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   335
                        // need to copy it to the local file system
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   336
                        Path tmpdir = Files.createTempDirectory("mlib");
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   337
                        Path target = Files.copy(entry, tmpdir.resolve(fn));
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   338
                        return readJar(target);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   339
                    }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   340
                }
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   341
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   342
                // JMOD file
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   343
                if (isDefaultFileSystem && isLinkPhase && fn.endsWith(".jmod")) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   344
                    return readJMod(entry);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   345
                }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   346
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   347
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   348
            return null;
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   349
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   350
        } catch (InvalidModuleDescriptorException e) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   351
            throw new FindException("Error reading module: " + entry, e);
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
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   354
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   355
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   356
     * Returns a string with the file name of the module if possible.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   357
     * 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
   358
     * as a string.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   359
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   360
    private String fileName(ModuleReference mref) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   361
        URI uri = mref.location().orElse(null);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   362
        if (uri != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   363
            if (uri.getScheme().equalsIgnoreCase("file")) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   364
                Path file = Paths.get(uri);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   365
                return file.getFileName().toString();
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 uri.toString();
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
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   370
            return "<unknown>";
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   371
        }
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
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   374
    // -- JMOD files --
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   375
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   376
    private Set<String> jmodPackages(JmodFile jf) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   377
        return jf.stream()
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   378
            .filter(e -> e.section() == Section.CLASSES)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   379
            .map(JmodFile.Entry::name)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   380
            .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   381
            .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   382
            .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   383
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   384
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   385
    /**
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   386
     * 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
   387
     * file system.
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
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   390
     * @throws InvalidModuleDescriptorException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   391
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   392
    private ModuleReference readJMod(Path file) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   393
        try (JmodFile jf = new JmodFile(file)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   394
            ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   395
            try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   396
                attrs  = ModuleInfo.read(in, () -> jmodPackages(jf));
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
            return ModuleReferences.newJModModule(attrs, file);
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
    }
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   403
    // -- JAR files --
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   404
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   405
    private static final String SERVICES_PREFIX = "META-INF/services/";
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   406
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
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   448
     * 1. The module name (and optionally the version) is derived from the file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   449
     *    name of the JAR file
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   450
     * 2. All packages are derived from the .class files in the JAR file
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   451
     * 3. The contents of any META-INF/services configuration files are mapped
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   452
     *    to "provides" declarations
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   453
     * 4. 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
   454
     *    is mapped to the module descriptor mainClass if possible
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   455
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   456
    private ModuleDescriptor deriveModuleDescriptor(JarFile jf)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   457
        throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   458
    {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   459
        // Derive module name and version from JAR file name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   460
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   461
        String fn = jf.getName();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   462
        int i = fn.lastIndexOf(File.separator);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   463
        if (i != -1)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   464
            fn = fn.substring(i+1);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   465
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   466
        // drop .jar
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   467
        String mn = fn.substring(0, fn.length()-4);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   468
        String vs = null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   469
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   470
        // find first occurrence of -${NUMBER}. or -${NUMBER}$
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   471
        Matcher matcher = Patterns.DASH_VERSION.matcher(mn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   472
        if (matcher.find()) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   473
            int start = matcher.start();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   474
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   475
            // attempt to parse the tail as a version string
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   476
            try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   477
                String tail = mn.substring(start+1);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   478
                ModuleDescriptor.Version.parse(tail);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   479
                vs = tail;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   480
            } catch (IllegalArgumentException ignore) { }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   481
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   482
            mn = mn.substring(0, start);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   483
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   484
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   485
        // finally clean up the module name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   486
        mn = cleanModuleName(mn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   487
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   488
        // Builder throws IAE if module name is empty or invalid
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   489
        ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(mn);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   490
        if (vs != null)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   491
            builder.version(vs);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   492
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   493
        // scan the names of the entries in the JAR file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   494
        Map<Boolean, Set<String>> map = VersionedStream.stream(jf)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   495
                .filter(e -> !e.isDirectory())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   496
                .map(JarEntry::getName)
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   497
                .filter(e -> (e.endsWith(".class") ^ e.startsWith(SERVICES_PREFIX)))
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   498
                .collect(Collectors.partitioningBy(e -> e.startsWith(SERVICES_PREFIX),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   499
                                                   Collectors.toSet()));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   500
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   501
        Set<String> classFiles = map.get(Boolean.FALSE);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   502
        Set<String> configFiles = map.get(Boolean.TRUE);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   503
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   504
        // the packages containing class files
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   505
        Set<String> packages = classFiles.stream()
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   506
                .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   507
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   508
                .distinct()
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   509
                .collect(Collectors.toSet());
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   510
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   511
        // all packages are exported and open
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   512
        builder.packages(packages);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   513
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   514
        // map names of service configuration files to service names
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   515
        Set<String> serviceNames = configFiles.stream()
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   516
                .map(this::toServiceName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   517
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   518
                .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   519
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   520
        // parse each service configuration file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   521
        for (String sn : serviceNames) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   522
            JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   523
            List<String> providerClasses = new ArrayList<>();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   524
            try (InputStream in = jf.getInputStream(entry)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   525
                BufferedReader reader
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   526
                    = new BufferedReader(new InputStreamReader(in, "UTF-8"));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   527
                String cn;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   528
                while ((cn = nextLine(reader)) != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   529
                    if (cn.length() > 0) {
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   530
                        String pn = packageName(cn);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   531
                        if (!packages.contains(pn)) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   532
                            String msg = "Provider class " + cn + " not in module";
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   533
                            throw new InvalidModuleDescriptorException(msg);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   534
                        }
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   535
                        providerClasses.add(cn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   536
                    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   537
                }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   538
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   539
            if (!providerClasses.isEmpty())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   540
                builder.provides(sn, providerClasses);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   541
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   542
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   543
        // Main-Class attribute if it exists
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   544
        Manifest man = jf.getManifest();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   545
        if (man != null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   546
            Attributes attrs = man.getMainAttributes();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   547
            String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   548
            if (mainClass != null) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   549
                mainClass = mainClass.replace("/", ".");
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   550
                if (Checks.isClassName(mainClass)) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   551
                    String pn = packageName(mainClass);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   552
                    if (packages.contains(pn)) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   553
                        builder.mainClass(mainClass);
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   554
                    }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   555
                }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   556
            }
42703
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
        return builder.build();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   560
    }
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
     * Patterns used to derive the module name from a JAR file name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   564
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   565
    private static class Patterns {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   566
        static final Pattern DASH_VERSION = Pattern.compile("-(\\d+(\\.|$))");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   567
        static final Pattern NON_ALPHANUM = Pattern.compile("[^A-Za-z0-9]");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   568
        static final Pattern REPEATING_DOTS = Pattern.compile("(\\.)(\\1)+");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   569
        static final Pattern LEADING_DOTS = Pattern.compile("^\\.");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   570
        static final Pattern TRAILING_DOTS = Pattern.compile("\\.$");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   571
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   572
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   573
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   574
     * Clean up candidate module name derived from a JAR file name.
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
    private static String cleanModuleName(String mn) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   577
        // replace non-alphanumeric
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   578
        mn = Patterns.NON_ALPHANUM.matcher(mn).replaceAll(".");
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
        // collapse repeating dots
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   581
        mn = Patterns.REPEATING_DOTS.matcher(mn).replaceAll(".");
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
        // drop leading dots
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   584
        if (mn.length() > 0 && mn.charAt(0) == '.')
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   585
            mn = Patterns.LEADING_DOTS.matcher(mn).replaceAll("");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   586
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   587
        // drop trailing dots
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   588
        int len = mn.length();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   589
        if (len > 0 && mn.charAt(len-1) == '.')
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   590
            mn = Patterns.TRAILING_DOTS.matcher(mn).replaceAll("");
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
        return mn;
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   595
    private Set<String> jarPackages(JarFile jf) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   596
        return VersionedStream.stream(jf)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   597
                .filter(e -> !e.isDirectory())
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   598
                .map(JarEntry::getName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   599
                .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   600
                .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   601
                .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   602
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   603
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
     * Returns a {@code ModuleReference} to a module in modular JAR file on
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   606
     * the file system.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   607
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   608
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   609
     * @throws FindException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   610
     * @throws InvalidModuleDescriptorException
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
    private ModuleReference readJar(Path file) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   613
        try (JarFile jf = new JarFile(file.toFile(),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   614
                                      true,               // verify
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   615
                                      ZipFile.OPEN_READ,
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   616
                                      releaseVersion))
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   617
        {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   618
            ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   619
            JarEntry entry = jf.getJarEntry(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   620
            if (entry == null) {
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
                // no module-info.class so treat it as automatic module
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   623
                try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   624
                    ModuleDescriptor md = deriveModuleDescriptor(jf);
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   625
                    attrs = new ModuleInfo.Attributes(md, null, null, null);
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   626
                } catch (RuntimeException e) {
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   627
                    throw new FindException("Unable to derive module descriptor for "
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   628
                                            + jf.getName(), e);
42703
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
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   631
            } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   632
                attrs = ModuleInfo.read(jf.getInputStream(entry),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   633
                                        () -> jarPackages(jf));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   634
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   635
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   636
            return ModuleReferences.newJarModule(attrs, patcher, file);
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   637
        } catch (ZipException e) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   638
            throw new FindException("Error reading " + file, e);
42703
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
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   641
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   642
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   643
    // -- exploded directories --
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   644
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   645
    private Set<String> explodedPackages(Path dir) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   646
        try {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   647
            return Files.find(dir, Integer.MAX_VALUE,
44545
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   648
                    ((path, attrs) -> attrs.isRegularFile() && !isHidden(path)))
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   649
                    .map(path -> dir.relativize(path))
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   650
                    .map(this::toPackageName)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   651
                    .flatMap(Optional::stream)
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   652
                    .collect(Collectors.toSet());
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   653
        } catch (IOException x) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   654
            throw new UncheckedIOException(x);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   655
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   656
    }
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
     * Returns a {@code ModuleReference} to an exploded module on the file
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   660
     * system or {@code null} if {@code module-info.class} not found.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   661
     *
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   662
     * @throws IOException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   663
     * @throws InvalidModuleDescriptorException
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   664
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   665
    private ModuleReference readExplodedModule(Path dir) throws IOException {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   666
        Path mi = dir.resolve(MODULE_INFO);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   667
        ModuleInfo.Attributes attrs;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   668
        try (InputStream in = Files.newInputStream(mi)) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   669
            attrs = ModuleInfo.read(new BufferedInputStream(in),
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   670
                                    () -> explodedPackages(dir));
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   671
        } catch (NoSuchFileException e) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   672
            // for now
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   673
            return null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   674
        }
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   675
        return ModuleReferences.newExplodedModule(attrs, patcher, dir);
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   676
    }
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   677
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   678
    /**
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   679
     * Maps a type name to its package name.
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   680
     */
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   681
    private static String packageName(String cn) {
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   682
        int index = cn.lastIndexOf('.');
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   683
        return (index == -1) ? "" : cn.substring(0, index);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   684
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   685
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   686
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   687
     * 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
   688
     *
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   689
     * @throws InvalidModuleDescriptorException if the name is a class file in
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   690
     *         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
   691
     *         module-info.class)
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   692
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   693
    private Optional<String> toPackageName(String name) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   694
        assert !name.endsWith("/");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   695
        int index = name.lastIndexOf("/");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   696
        if (index == -1) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   697
            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   698
                String msg = name + " found in top-level directory"
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   699
                             + " (unnamed package not allowed in module)";
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   700
                throw new InvalidModuleDescriptorException(msg);
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   701
            }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   702
            return Optional.empty();
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
        String pn = name.substring(0, index).replace('/', '.');
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   706
        if (Checks.isPackageName(pn)) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   707
            return Optional.of(pn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   708
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   709
            // not a valid package name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   710
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   711
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   712
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   713
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   714
    /**
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   715
     * 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
   716
     * name.
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   717
     *
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   718
     * @throws InvalidModuleDescriptorException if the name is a class file in
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   719
     *         the top-level directory (and it's not module-info.class)
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   720
     */
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   721
    private Optional<String> toPackageName(Path file) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   722
        assert file.getRoot() == null;
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   723
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   724
        Path parent = file.getParent();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   725
        if (parent == null) {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   726
            String name = file.toString();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   727
            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
44359
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   728
                String msg = name + " found in top-level directory"
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   729
                             + " (unnamed package not allowed in module)";
c6761862ca0b 8174823: Module system implementation refresh (3/2017)
alanb
parents: 43712
diff changeset
   730
                throw new InvalidModuleDescriptorException(msg);
42703
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
            return Optional.empty();
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   733
        }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   734
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   735
        String pn = parent.toString().replace(File.separatorChar, '.');
43712
5dfd0950317c 8173393: Module system implementation refresh (2/2017)
alanb
parents: 42703
diff changeset
   736
        if (Checks.isPackageName(pn)) {
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   737
            return Optional.of(pn);
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   738
        } else {
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   739
            // not a valid package name
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   740
            return Optional.empty();
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
    }
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   743
44545
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   744
    /**
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   745
     * 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
   746
     */
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   747
    private boolean isHidden(Path file) {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   748
        try {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   749
            return Files.isHidden(file);
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   750
        } catch (IOException ioe) {
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   751
            return false;
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   752
        }
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   753
    }
83b611b88ac8 8177530: Module system implementation refresh (4/2017)
alanb
parents: 44359
diff changeset
   754
45004
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   755
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   756
    /**
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   757
     * 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
   758
     */
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   759
    private boolean isDefaultFileSystem(Path path) {
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   760
        return path.getFileSystem().provider()
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   761
                .getScheme().equalsIgnoreCase("file");
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   762
    }
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   763
ea3137042a61 8178380: Module system implementation refresh (5/2017)
alanb
parents: 44545
diff changeset
   764
42703
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   765
    private static final PerfCounter scanTime
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   766
        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.scanTime");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   767
    private static final PerfCounter moduleCount
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   768
        = PerfCounter.newPerfCounter("jdk.module.finder.modulepath.modules");
20c39ea4a507 8170987: Module system implementation refresh (12/2016)
alanb
parents:
diff changeset
   769
}