langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
changeset 30846 2b3f379840f0
parent 27579 d1a63c99cdd5
child 34752 9c262a013456
equal deleted inserted replaced
30845:43ddd58a5a56 30846:2b3f379840f0
       
     1 /*
       
     2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package com.sun.tools.jdeps;
       
    26 
       
    27 import java.util.Collections;
       
    28 import java.util.HashMap;
       
    29 import java.util.HashSet;
       
    30 import java.util.Map;
       
    31 import java.util.Objects;
       
    32 import java.util.Set;
       
    33 
       
    34 /**
       
    35  * JDeps internal representation of module for dependency analysis.
       
    36  */
       
    37 final class Module extends Archive {
       
    38     private final String moduleName;
       
    39     private final Map<String, Boolean> requires;
       
    40     private final Map<String, Set<String>> exports;
       
    41     private final Set<String> packages;
       
    42 
       
    43     private Module(ClassFileReader reader, String name,
       
    44                    Map<String, Boolean> requires,
       
    45                    Map<String, Set<String>> exports,
       
    46                    Set<String> packages) {
       
    47         super(name, reader);
       
    48         this.moduleName = name;
       
    49         this.requires = Collections.unmodifiableMap(requires);
       
    50         this.exports = Collections.unmodifiableMap(exports);
       
    51         this.packages = Collections.unmodifiableSet(packages);
       
    52     }
       
    53 
       
    54     public String name() {
       
    55         return moduleName;
       
    56     }
       
    57 
       
    58     public Map<String, Boolean> requires() {
       
    59         return requires;
       
    60     }
       
    61 
       
    62     public Map<String, Set<String>> exports() {
       
    63         return exports;
       
    64     }
       
    65 
       
    66     public Set<String> packages() {
       
    67         return packages;
       
    68     }
       
    69 
       
    70     /**
       
    71      * Tests if this module can read m
       
    72      */
       
    73     public boolean canRead(Module m) {
       
    74         // ## TODO: handle "re-exported=true"
       
    75         // all JDK modules require all modules containing its direct dependences
       
    76         // should not be an issue
       
    77         return requires.containsKey(m.name());
       
    78     }
       
    79 
       
    80     /**
       
    81      * Tests if a given fully-qualified name is an exported type.
       
    82      */
       
    83     public boolean isExported(String cn) {
       
    84         int i = cn.lastIndexOf('.');
       
    85         String pn = i > 0 ? cn.substring(0, i) : "";
       
    86 
       
    87         return isExportedPackage(pn);
       
    88     }
       
    89 
       
    90     /**
       
    91      * Tests if a given package name is exported.
       
    92      */
       
    93     public boolean isExportedPackage(String pn) {
       
    94         return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false;
       
    95     }
       
    96 
       
    97     /**
       
    98      * Tests if the given classname is accessible to module m
       
    99      */
       
   100     public boolean isAccessibleTo(String classname, Module m) {
       
   101         int i = classname.lastIndexOf('.');
       
   102         String pn = i > 0 ? classname.substring(0, i) : "";
       
   103         if (!packages.contains(pn)) {
       
   104             throw new IllegalArgumentException(classname + " is not a member of module " + name());
       
   105         }
       
   106 
       
   107         if (m != null && !m.canRead(this)) {
       
   108             trace("%s not readable by %s%n", this.name(), m.name());
       
   109             return false;
       
   110         }
       
   111 
       
   112         // exported API
       
   113         Set<String> ms = exports().get(pn);
       
   114         String mname = m != null ? m.name() : "unnamed";
       
   115         if (ms == null) {
       
   116             trace("%s not exported in %s%n", classname, this.name());
       
   117         } else if (!(ms.isEmpty() || ms.contains(mname))) {
       
   118             trace("%s not permit to %s %s%n", classname, mname, ms);
       
   119         }
       
   120         return ms != null && (ms.isEmpty() || ms.contains(mname));
       
   121     }
       
   122 
       
   123     private static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
       
   124     private void trace(String fmt, Object... args) {
       
   125         if (traceOn) {
       
   126             System.err.format(fmt, args);
       
   127         }
       
   128     }
       
   129 
       
   130     @Override
       
   131     public boolean equals(Object ob) {
       
   132         if (!(ob instanceof Module))
       
   133             return false;
       
   134         Module that = (Module)ob;
       
   135         return (moduleName.equals(that.moduleName)
       
   136                 && requires.equals(that.requires)
       
   137                 && exports.equals(that.exports)
       
   138                 && packages.equals(that.packages));
       
   139     }
       
   140 
       
   141     @Override
       
   142     public int hashCode() {
       
   143         int hc = moduleName.hashCode();
       
   144         hc = hc * 43 + requires.hashCode();
       
   145         hc = hc * 43 + exports.hashCode();
       
   146         hc = hc * 43 + packages.hashCode();
       
   147         return hc;
       
   148     }
       
   149 
       
   150     @Override
       
   151     public String toString() {
       
   152         return name();
       
   153     }
       
   154 
       
   155     public final static class Builder {
       
   156         String name;
       
   157         ClassFileReader reader;
       
   158         final Map<String, Boolean> requires = new HashMap<>();
       
   159         final Map<String, Set<String>> exports = new HashMap<>();
       
   160         final Set<String> packages = new HashSet<>();
       
   161 
       
   162         public Builder() {
       
   163         }
       
   164 
       
   165         public Builder name(String n) {
       
   166             name = n;
       
   167             return this;
       
   168         }
       
   169 
       
   170         public Builder require(String d, boolean reexport) {
       
   171          //   System.err.format("%s depend %s reexports %s%n", name, d, reexport);
       
   172             requires.put(d, reexport);
       
   173             return this;
       
   174         }
       
   175 
       
   176         public Builder packages(Set<String> pkgs) {
       
   177             packages.addAll(pkgs);
       
   178             return this;
       
   179         }
       
   180 
       
   181         public Builder export(String p, Set<String> ms) {
       
   182             Objects.requireNonNull(p);
       
   183             Objects.requireNonNull(ms);
       
   184             exports.put(p, new HashSet<>(ms));
       
   185             return this;
       
   186         }
       
   187         public Builder classes(ClassFileReader.ModuleClassReader reader) {
       
   188             this.reader = reader;
       
   189             return this;
       
   190         }
       
   191 
       
   192         public Module build() {
       
   193             Module m = new Module(reader, name, requires, exports, packages);
       
   194             return m;
       
   195         }
       
   196     }
       
   197 }