SmartFileManager.java revision 2721:f7ce2cfa4cdb
150472Speter/* 237Srgrimes * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 337Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 437Srgrimes * 527086Swosch * This code is free software; you can redistribute it and/or modify it 637Srgrimes * under the terms of the GNU General Public License version 2 only, as 737Srgrimes * published by the Free Software Foundation. Oracle designates this 837Srgrimes * particular file as subject to the "Classpath" exception as provided 937Srgrimes * by Oracle in the LICENSE file that accompanied this code. 1037Srgrimes * 1127086Swosch * This code is distributed in the hope that it will be useful, but WITHOUT 1227086Swosch * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1327086Swosch * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1437Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 1540855Sphk * accompanied this code). 1642294Sbillf * 1740855Sphk * You should have received a copy of the GNU General Public License version 1827086Swosch * 2 along with this work; if not, write to the Free Software Foundation, 1940855Sphk * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2040855Sphk * 2137Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2237Srgrimes * or visit www.oracle.com if you need additional information or have any 2337Srgrimes * questions. 2437Srgrimes */ 2537Srgrimes 2637Srgrimespackage com.sun.tools.sjavac.comp; 2737Srgrimes 2837Srgrimesimport java.io.IOException; 2927086Swoschimport java.io.PrintWriter; 3027086Swoschimport java.net.URI; 3137Srgrimesimport java.util.HashMap; 3227086Swoschimport java.util.HashSet; 3343781Sdesimport java.util.Map; 3437Srgrimesimport java.util.Set; 3537Srgrimes 3627086Swoschimport javax.tools.*; 3737Srgrimesimport javax.tools.JavaFileObject.Kind; 3827086Swosch 3937Srgrimesimport com.sun.tools.javac.file.JavacFileManager; 40153Srgrimesimport com.sun.tools.javac.util.DefinedBy; 41153Srgrimesimport com.sun.tools.javac.util.DefinedBy.Api; 42153Srgrimesimport com.sun.tools.javac.util.ListBuffer; 4312389Sache 4427086Swosch/** 4527086Swosch * Intercepts reads and writes to the file system to gather 4627086Swosch * information about what artifacts are generated. 4727086Swosch * 4827086Swosch * Traps writes to certain files, if the content written is identical 4927086Swosch * to the existing file. 5027086Swosch * 5128428Swosch * Can also blind out the filemanager from seeing certain files in the file system. 5227086Swosch * Necessary to prevent javac from seeing some sources where the source path points. 5328428Swosch * 5427086Swosch * <p><b>This is NOT part of any supported API. 5527086Swosch * If you write code that depends on this, you do so at your own risk. 5628428Swosch * This code and its internal interfaces are subject to change or 5728428Swosch * deletion without notice.</b> 5827086Swosch */ 5927086Swosch@com.sun.tools.javac.api.ClientCodeWrapper.Trusted 6027086Swoschpublic class SmartFileManager extends ForwardingJavaFileManager<JavaFileManager> { 6127086Swosch 6212389Sache // Set of sources that can be seen by javac. 6327086Swosch Set<URI> visibleSources = new HashSet<>(); 6427086Swosch // Map from modulename:packagename to artifacts. 65 Map<String,Set<URI>> packageArtifacts = new HashMap<>(); 66 // Where to print informational messages. 67 PrintWriter stdout; 68 69 public SmartFileManager(JavaFileManager fileManager) { 70 super(fileManager); 71 } 72 73 public void setVisibleSources(Set<URI> s) { 74 visibleSources = s; 75 } 76 77 public void cleanArtifacts() { 78 packageArtifacts = new HashMap<>(); 79 } 80 81 public void setLog(PrintWriter pw) { 82 stdout = pw; 83 } 84 85 /** 86 * Set whether or not to use ct.sym as an alternate to rt.jar. 87 */ 88 public void setSymbolFileEnabled(boolean b) { 89 if (!(fileManager instanceof JavacFileManager)) 90 throw new IllegalStateException(); 91 ((JavacFileManager) fileManager).setSymbolFileEnabled(b); 92 } 93 94 public Map<String,Set<URI>> getPackageArtifacts() { 95 return packageArtifacts; 96 } 97 98 @Override @DefinedBy(Api.COMPILER) 99 public Iterable<JavaFileObject> list(Location location, 100 String packageName, 101 Set<Kind> kinds, 102 boolean recurse) throws IOException { 103 // Acquire the list of files. 104 Iterable<JavaFileObject> files = super.list(location, packageName, kinds, recurse); 105 if (visibleSources.isEmpty()) { 106 return files; 107 } 108 // Now filter! 109 ListBuffer<JavaFileObject> filteredFiles = new ListBuffer<>(); 110 for (JavaFileObject f : files) { 111 URI uri = f.toUri(); 112 String t = uri.toString(); 113 if (t.startsWith("jar:") 114 || t.endsWith(".class") 115 || visibleSources.contains(uri)) { 116 filteredFiles.add(f); 117 } 118 } 119 return filteredFiles; 120 } 121 122 @Override @DefinedBy(Api.COMPILER) 123 public boolean hasLocation(Location location) { 124 return super.hasLocation(location); 125 } 126 127 @Override @DefinedBy(Api.COMPILER) 128 public JavaFileObject getJavaFileForInput(Location location, 129 String className, 130 Kind kind) throws IOException { 131 JavaFileObject file = super.getJavaFileForInput(location, className, kind); 132 if (file == null || visibleSources.isEmpty()) { 133 return file; 134 } 135 136 if (visibleSources.contains(file.toUri())) { 137 return file; 138 } 139 return null; 140 } 141 142 @Override @DefinedBy(Api.COMPILER) 143 public JavaFileObject getJavaFileForOutput(Location location, 144 String className, 145 Kind kind, 146 FileObject sibling) throws IOException { 147 JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); 148 if (file == null) return file; 149 int dp = className.lastIndexOf('.'); 150 String pkg_name = ""; 151 if (dp != -1) { 152 pkg_name = className.substring(0, dp); 153 } 154 // When modules are in use, then the mod_name might be something like "jdk_base" 155 String mod_name = ""; 156 addArtifact(mod_name+":"+pkg_name, file.toUri()); 157 return file; 158 } 159 160 @Override @DefinedBy(Api.COMPILER) 161 public FileObject getFileForInput(Location location, 162 String packageName, 163 String relativeName) throws IOException { 164 FileObject file = super.getFileForInput(location, packageName, relativeName); 165 if (file == null || visibleSources.isEmpty()) { 166 return file; 167 } 168 169 if (visibleSources.contains(file.toUri())) { 170 return file; 171 } 172 return null; 173 } 174 175 @Override @DefinedBy(Api.COMPILER) 176 public FileObject getFileForOutput(Location location, 177 String packageName, 178 String relativeName, 179 FileObject sibling) throws IOException { 180 FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling); 181 if (file == null) return file; 182 if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && 183 file instanceof JavaFileObject) { 184 file = new SmartFileObject((JavaFileObject)file, stdout); 185 packageName = ":" + packageNameFromFileName(relativeName); 186 } 187 if (packageName.equals("")) { 188 packageName = ":"; 189 } 190 addArtifact(packageName, file.toUri()); 191 return file; 192 } 193 194 private String packageNameFromFileName(String fn) { 195 StringBuilder sb = new StringBuilder(); 196 int p = fn.indexOf('_'), pp = 0; 197 while (p != -1) { 198 if (sb.length() > 0) sb.append('.'); 199 sb.append(fn.substring(pp,p)); 200 if (p == fn.length()-1) break; 201 pp = p+1; 202 p = fn.indexOf('_',pp); 203 } 204 return sb.toString(); 205 } 206 207 @Override @DefinedBy(Api.COMPILER) 208 public void flush() throws IOException { 209 super.flush(); 210 } 211 212 @Override @DefinedBy(Api.COMPILER) 213 public void close() throws IOException { 214 super.close(); 215 } 216 217 void addArtifact(String pkgName, URI art) { 218 Set<URI> s = packageArtifacts.get(pkgName); 219 if (s == null) { 220 s = new HashSet<>(); 221 packageArtifacts.put(pkgName, s); 222 } 223 s.add(art); 224 } 225} 226