src/share/classes/com/sun/tools/sjavac/Package.java

Mon, 11 Mar 2013 19:03:35 -0700

author
ohrstrom
date
Mon, 11 Mar 2013 19:03:35 -0700
changeset 1625
fbb6e470079d
parent 1504
22e417cdddee
child 2227
998b10c43157
permissions
-rw-r--r--

8009843: sjavac should accept -cp as synonym for -classpath
Reviewed-by: jjg

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

mercurial