Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
41161 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdeps;2627import java.lang.module.ModuleDescriptor;28import java.net.URI;29import java.util.Collections;30import java.util.HashMap;31import java.util.HashSet;32import java.util.Map;33import java.util.Set;3435/**36* Jdeps internal representation of module for dependency analysis.37*/38class Module extends Archive {39static final Module UNNAMED_MODULE = new UnnamedModule();40static final String JDK_UNSUPPORTED = "jdk.unsupported";4142static final boolean DEBUG = Boolean.getBoolean("jdeps.debug");43static void trace(String fmt, Object... args) {44trace(DEBUG, fmt, args);45}4647static void trace(boolean traceOn, String fmt, Object... args) {48if (traceOn) {49System.err.format(fmt, args);50}51}5253private final ModuleDescriptor descriptor;54private final Map<String, Set<String>> exports;55private final Map<String, Set<String>> opens;56private final boolean isSystem;57private final URI location;5859protected Module(String name) {60this(name, null, false);61}6263protected Module(String name, ModuleDescriptor descriptor, boolean isSystem) {64super(name);65this.descriptor = descriptor;66this.location = null;67this.exports = Collections.emptyMap();68this.opens = Collections.emptyMap();69this.isSystem = isSystem;70}7172private Module(String name,73URI location,74ModuleDescriptor descriptor,75Map<String, Set<String>> exports,76Map<String, Set<String>> opens,77boolean isSystem,78ClassFileReader reader) {79super(name, location, reader);80this.descriptor = descriptor;81this.location = location;82this.exports = Collections.unmodifiableMap(exports);83this.opens = Collections.unmodifiableMap(opens);84this.isSystem = isSystem;85}8687/**88* Returns module name89*/90public String name() {91return descriptor != null ? descriptor.name() : getName();92}9394public boolean isNamed() {95return descriptor != null;96}9798public boolean isAutomatic() {99return descriptor != null && descriptor.isAutomatic();100}101102public Module getModule() {103return this;104}105106public ModuleDescriptor descriptor() {107return descriptor;108}109110public URI location() {111return location;112}113114public boolean isJDK() {115String mn = name();116return isSystem &&117(mn.startsWith("java.") || mn.startsWith("jdk."));118}119120public boolean isSystem() {121return isSystem;122}123124public Map<String, Set<String>> exports() {125return exports;126}127128public Set<String> packages() {129return descriptor.packages();130}131132public boolean isJDKUnsupported() {133return JDK_UNSUPPORTED.equals(this.name());134}135136/**137* Converts this module to a normal module with the given dependences138*139* @throws IllegalArgumentException if this module is not an automatic module140*/141public Module toNormalModule(Map<String, Boolean> requires) {142if (!isAutomatic()) {143throw new IllegalArgumentException(name() + " not an automatic module");144}145return new NormalModule(this, requires);146}147148/**149* Tests if the package of the given name is exported.150*/151public boolean isExported(String pn) {152return exports.containsKey(pn) && exports.get(pn).isEmpty();153}154155/**156* Tests if the package of the given name is exported to the target157* in a qualified fashion.158*/159public boolean isExported(String pn, String target) {160return isExported(pn)161|| exports.containsKey(pn) && exports.get(pn).contains(target);162}163164/**165* Tests if the package of the given name is open.166*/167public boolean isOpen(String pn) {168return opens.containsKey(pn) && opens.get(pn).isEmpty();169}170171/**172* Tests if the package of the given name is open to the target173* in a qualified fashion.174*/175public boolean isOpen(String pn, String target) {176return isOpen(pn)177|| opens.containsKey(pn) && opens.get(pn).contains(target);178}179180@Override181public String toString() {182return name();183}184185public final static class Builder {186final String name;187final ModuleDescriptor descriptor;188final boolean isSystem;189ClassFileReader reader;190URI location;191192public Builder(ModuleDescriptor md) {193this(md, false);194}195196public Builder(ModuleDescriptor md, boolean isSystem) {197this.name = md.name();198this.descriptor = md;199this.isSystem = isSystem;200}201202public Builder location(URI location) {203this.location = location;204return this;205}206207public Builder classes(ClassFileReader reader) {208this.reader = reader;209return this;210}211212public Module build() {213if (descriptor.isAutomatic() && isSystem) {214throw new InternalError("JDK module: " + name + " can't be automatic module");215}216217Map<String, Set<String>> exports = new HashMap<>();218Map<String, Set<String>> opens = new HashMap<>();219220if (descriptor.isAutomatic()) {221// ModuleDescriptor::exports and opens returns an empty set222descriptor.packages().forEach(pn -> exports.put(pn, Collections.emptySet()));223descriptor.packages().forEach(pn -> opens.put(pn, Collections.emptySet()));224} else {225descriptor.exports().stream()226.forEach(exp -> exports.computeIfAbsent(exp.source(), _k -> new HashSet<>())227.addAll(exp.targets()));228descriptor.opens().stream()229.forEach(exp -> opens.computeIfAbsent(exp.source(), _k -> new HashSet<>())230.addAll(exp.targets()));231}232return new Module(name, location, descriptor, exports, opens, isSystem, reader);233}234}235236private static class UnnamedModule extends Module {237private UnnamedModule() {238super("unnamed", null, false);239}240241@Override242public String name() {243return "unnamed";244}245246@Override247public boolean isExported(String pn) {248return true;249}250}251252/**253* A normal module has a module-info.class254*/255private static class NormalModule extends Module {256private final ModuleDescriptor md;257258/**259* Converts the given automatic module to a normal module.260*261* Replace this module's dependences with the given requires and also262* declare service providers, if specified in META-INF/services configuration file263*/264private NormalModule(Module m, Map<String, Boolean> requires) {265super(m.name(), m.location, m.descriptor, m.exports, m.opens, m.isSystem, m.reader());266267ModuleDescriptor.Builder builder = ModuleDescriptor.newModule(m.name());268requires.keySet().forEach(mn -> {269if (requires.get(mn).equals(Boolean.TRUE)) {270builder.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), mn);271} else {272builder.requires(mn);273}274});275// exports all packages276m.descriptor.packages().forEach(builder::exports);277m.descriptor.uses().forEach(builder::uses);278m.descriptor.provides().forEach(builder::provides);279this.md = builder.build();280}281282@Override283public ModuleDescriptor descriptor() {284return md;285}286}287}288289290