Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/sjavac/Package.java
38899 views
/*1* Copyright (c) 2012, 2013, 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.sjavac;2627import java.io.File;28import java.net.URI;29import java.util.ArrayList;30import java.util.Collections;31import java.util.HashMap;32import java.util.HashSet;33import java.util.Iterator;34import java.util.List;35import java.util.Map;36import java.util.Set;3738/**39* The Package class maintains meta information about a package.40* For example its sources, dependents,its pubapi and its artifacts.41*42* It might look odd that we track dependents/pubapi/artifacts on43* a package level, but it makes sense since recompiling a full package44* takes as long as recompiling a single java file in that package,45* if you take into account the startup time of the jvm.46*47* Also the dependency information will be much smaller (good for the javac_state file size)48* and it simplifies tracking artifact generation, you do not always know from which49* source a class file was generated, but you always know which package it belongs to.50*51* It is also educational to see package dependencies triggering recompilation of52* other packages. Even though the recompilation was perhaps not necessary,53* the visible recompilation of the dependent packages indicates how much circular54* dependencies your code has.55*56* <p><b>This is NOT part of any supported API.57* If you write code that depends on this, you do so at your own58* risk. This code and its internal interfaces are subject to change59* or deletion without notice.</b></p>60*/61public class Package implements Comparable<Package> {62// The module this package belongs to. (There is a legacy module with an empty string name,63// used for all legacy sources.)64private Module mod;65// Name of this package, module:pkg66// ex1 jdk.base:java.lang67// ex2 :java.lang (when in legacy mode)68private String name;69// The directory path to the package. If the package belongs to a module,70// then that module's file system name is part of the path.71private String dirname;72// This package depends on these packages.73private Set<String> dependencies = new HashSet<String>();74// This package has the following dependents, that depend on this package.75private Set<String> dependents = new HashSet<String>();76// This is the public api of this package.77private List<String> pubapi = new ArrayList<String>();78// Map from source file name to Source info object.79private Map<String,Source> sources = new HashMap<String,Source>();80// This package generated these artifacts.81private Map<String,File> artifacts = new HashMap<String,File>();8283public Package(Module m, String n) {84int c = n.indexOf(":");85assert(c != -1);86String mn = n.substring(0,c);87assert(m.name().equals(m.name()));88name = n;89dirname = n.replace('.', File.separatorChar);90if (m.name().length() > 0) {91// There is a module here, prefix the module dir name to the path.92dirname = m.dirname()+File.separatorChar+dirname;93}94}9596public Module mod() { return mod; }97public String name() { return name; }98public String dirname() { return dirname; }99public Map<String,Source> sources() { return sources; }100public Map<String,File> artifacts() { return artifacts; }101public List<String> pubapi() { return pubapi; }102103public Set<String> dependencies() { return dependencies; }104public Set<String> dependents() { return dependents; }105106@Override107public boolean equals(Object o) {108return (o instanceof Package) && name.equals(((Package)o).name);109}110111@Override112public int hashCode() {113return name.hashCode();114}115116@Override117public int compareTo(Package o) {118return name.compareTo(o.name);119}120121public void addSource(Source s) {122sources.put(s.file().getPath(), s);123}124125public void addDependency(String d) {126dependencies.add(d);127}128129public void addDependent(String d) {130dependents.add(d);131}132133public void addPubapi(String p) {134pubapi.add(p);135}136137/**138* Check if we have knowledge in the javac state that139* describe the results of compiling this package before.140*/141public boolean existsInJavacState() {142return artifacts.size() > 0 || pubapi.size() > 0;143}144145public static List<String> pubapiToList(String ps)146{147String[] lines = ps.split("\n");148List<String> r = new ArrayList<String>();149for (String l : lines) {150r.add(l);151}152return r;153}154155public boolean hasPubapiChanged(List<String> ps) {156Iterator<String> i = ps.iterator();157Iterator<String> j = pubapi.iterator();158int line = 0;159while (i.hasNext() && j.hasNext()) {160String is = i.next();161String js = j.next();162if (!is.equals(js)) {163Log.debug("Change in pubapi for package "+name+" line "+line);164Log.debug("Old: "+js);165Log.debug("New: "+is);166return true;167}168line++;169}170if ((i.hasNext() && !j.hasNext() ) ||171(!i.hasNext() && j.hasNext())) {172Log.debug("Change in pubapi for package "+name);173if (i.hasNext()) {174Log.debug("New has more lines!");175} else {176Log.debug("Old has more lines!");177}178return true;179}180return false;181}182183public void setPubapi(List<String> ps) {184pubapi = ps;185}186187public void setDependencies(Set<String> ds) {188dependencies = ds;189}190191public void save(StringBuilder b) {192b.append("P ").append(name).append("\n");193Source.saveSources(sources, b);194saveDependencies(b);195savePubapi(b);196saveArtifacts(b);197}198199static public Package load(Module module, String l) {200String name = l.substring(2);201return new Package(module, name);202}203204public void loadDependency(String l) {205String n = l.substring(2);206addDependency(n);207}208209public void loadPubapi(String l) {210String pi = l.substring(2);211addPubapi(pi);212}213214public void saveDependencies(StringBuilder b) {215List<String> sorted_dependencies = new ArrayList<String>();216for (String key : dependencies) {217sorted_dependencies.add(key);218}219Collections.sort(sorted_dependencies);220for (String a : sorted_dependencies) {221b.append("D "+a+"\n");222}223}224225public void savePubapi(StringBuilder b) {226for (String l : pubapi) {227b.append("I "+l+"\n");228}229}230231public static void savePackages(Map<String,Package> packages, StringBuilder b) {232List<String> sorted_packages = new ArrayList<String>();233for (String key : packages.keySet() ) {234sorted_packages.add(key);235}236Collections.sort(sorted_packages);237for (String s : sorted_packages) {238Package p = packages.get(s);239p.save(b);240}241}242243public void addArtifact(String a) {244artifacts.put(a, new File(a));245}246247public void addArtifact(File f) {248artifacts.put(f.getPath(), f);249}250251public void addArtifacts(Set<URI> as) {252for (URI u : as) {253addArtifact(new File(u));254}255}256257public void setArtifacts(Set<URI> as) {258assert(!artifacts.isEmpty());259artifacts = new HashMap<String,File>();260addArtifacts(as);261}262263public void loadArtifact(String l) {264// Find next space after "A ".265int dp = l.indexOf(' ',2);266String fn = l.substring(2,dp);267long last_modified = Long.parseLong(l.substring(dp+1));268File f = new File(fn);269if (f.exists() && f.lastModified() != last_modified) {270// Hmm, the artifact on disk does not have the same last modified271// timestamp as the information from the build database.272// We no longer trust the artifact on disk. Delete it.273// The smart javac wrapper will then rebuild the artifact.274Log.debug("Removing "+f.getPath()+" since its timestamp does not match javac_state.");275f.delete();276}277artifacts.put(f.getPath(), f);278}279280public void saveArtifacts(StringBuilder b) {281List<File> sorted_artifacts = new ArrayList<File>();282for (File f : artifacts.values()) {283sorted_artifacts.add(f);284}285Collections.sort(sorted_artifacts);286for (File f : sorted_artifacts) {287// The last modified information is only used288// to detect tampering with the output dir.289// If the outputdir has been modified, not by javac,290// then a mismatch will be detected in the last modified291// timestamps stored in the build database compared292// to the timestamps on disk and the artifact will be deleted.293294b.append("A "+f.getPath()+" "+f.lastModified()+"\n");295}296}297298/**299* Always clean out a tainted package before it is recompiled.300*/301public void deleteArtifacts() {302for (File a : artifacts.values()) {303a.delete();304}305}306}307308309