1 /* 2 * Copyright (c) 2012, 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 26 package com.sun.tools.sjavac.comp; 27 28 import java.io.IOException; 29 import java.io.PrintWriter; 30 import java.net.URI; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Map; 34 import java.util.Set; 35 36 import javax.tools.*; 37 import javax.tools.JavaFileObject.Kind; 38 39 import com.sun.tools.javac.file.JavacFileManager; 40 import com.sun.tools.javac.util.DefinedBy; 41 import com.sun.tools.javac.util.DefinedBy.Api; 42 import com.sun.tools.javac.util.ListBuffer; 43 44 /** 45 * Intercepts reads and writes to the file system to gather 46 * information about what artifacts are generated. 47 * 48 * Traps writes to certain files, if the content written is identical 49 * to the existing file. 50 * 51 * Can also blind out the filemanager from seeing certain files in the file system. 52 * Necessary to prevent javac from seeing some sources where the source path points. 53 * 54 * <p><b>This is NOT part of any supported API. 55 * If you write code that depends on this, you do so at your own risk. 56 * This code and its internal interfaces are subject to change or 57 * deletion without notice.</b> 58 */ 59 @com.sun.tools.javac.api.ClientCodeWrapper.Trusted 60 public class SmartFileManager extends ForwardingJavaFileManager<JavaFileManager> { 61 62 // Set of sources that can be seen by javac. 63 Set<URI> visibleSources = new HashSet<>(); 64 // 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 @DefinedBy(Api.COMPILER) 95 public String inferBinaryName(Location location, JavaFileObject file) { 96 return super.inferBinaryName(location, locUnwrap(file)); 97 } 98 99 100 public Map<String,Set<URI>> getPackageArtifacts() { 101 return packageArtifacts; 102 } 103 104 @Override @DefinedBy(Api.COMPILER) 105 public Iterable<JavaFileObject> list(Location location, 106 String packageName, 107 Set<Kind> kinds, 108 boolean recurse) throws IOException { 109 // TODO: Do this lazily by returning an iterable with a filtering Iterator 110 // Acquire the list of files. 111 Iterable<JavaFileObject> files = super.list(location, packageName, kinds, recurse); 112 if (visibleSources.isEmpty()) { 113 return locWrapMany(files, location); 114 } 115 // Now filter! 116 ListBuffer<JavaFileObject> filteredFiles = new ListBuffer<>(); 117 for (JavaFileObject f : files) { 118 URI uri = f.toUri(); 119 String t = uri.toString(); 120 if (t.startsWith("jar:") 121 || t.endsWith(".class") 122 || visibleSources.contains(uri)) { 123 filteredFiles.add(f); 124 } 125 } 126 127 return locWrapMany(filteredFiles, location); 128 } 129 130 @Override @DefinedBy(Api.COMPILER) 131 public JavaFileObject getJavaFileForInput(Location location, 132 String className, 133 Kind kind) throws IOException { 134 JavaFileObject file = super.getJavaFileForInput(location, className, kind); 135 file = locWrap(file, location); 136 if (file == null || visibleSources.isEmpty()) { 137 return file; 138 } 139 140 if (visibleSources.contains(file.toUri())) { 141 return file; 142 } 143 return null; 144 } 145 146 @Override @DefinedBy(Api.COMPILER) 147 public JavaFileObject getJavaFileForOutput(Location location, 148 String className, 149 Kind kind, 150 FileObject sibling) throws IOException { 151 JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); 152 file = locWrap(file, location); 153 if (file == null) return file; 154 int dp = className.lastIndexOf('.'); 155 String pkg_name = ""; 156 if (dp != -1) { 157 pkg_name = className.substring(0, dp); 158 } 159 // When modules are in use, then the mod_name might be something like "jdk_base" 160 String mod_name = ""; 161 addArtifact(mod_name+":"+pkg_name, file.toUri()); 162 return file; 163 } 164 165 @Override @DefinedBy(Api.COMPILER) 166 public FileObject getFileForInput(Location location, 167 String packageName, 168 String relativeName) throws IOException { 169 FileObject file = super.getFileForInput(location, packageName, relativeName); 170 file = locWrap(file, location); 171 if (file == null || visibleSources.isEmpty()) { 172 return file; 173 } 174 175 if (visibleSources.contains(file.toUri())) { 176 return file; 177 } 178 return null; 179 } 180 181 @Override @DefinedBy(Api.COMPILER) 182 public FileObject getFileForOutput(Location location, 183 String packageName, 184 String relativeName, 185 FileObject sibling) throws IOException { 186 FileObject superFile = super.getFileForOutput(location, packageName, relativeName, sibling); 187 FileObject file = locWrap(superFile, location); 188 if (file == null) return file; 189 190 if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && superFile instanceof JavaFileObject) { 191 file = new SmartFileObject((JavaFileObject) file, stdout); 192 packageName = ":" + packageNameFromFileName(relativeName); 193 } 194 if (packageName.equals("")) { 195 packageName = ":"; 196 } 197 addArtifact(packageName, file.toUri()); 198 return file; 199 } 200 201 private static String packageNameFromFileName(String fn) { 202 StringBuilder sb = new StringBuilder(); 203 int p = fn.indexOf('_'), pp = 0; 204 while (p != -1) { 205 if (sb.length() > 0) sb.append('.'); 206 sb.append(fn.substring(pp,p)); 207 if (p == fn.length()-1) break; 208 pp = p+1; 209 p = fn.indexOf('_',pp); 210 } 211 return sb.toString(); 212 } 213 214 void addArtifact(String pkgName, URI art) { 215 Set<URI> s = packageArtifacts.get(pkgName); 216 if (s == null) { 217 s = new HashSet<>(); 218 packageArtifacts.put(pkgName, s); 219 } 220 s.add(art); 221 } 222 223 private static JavaFileObject locWrap(JavaFileObject jfo, Location loc) { 224 return jfo == null ? null : new JavaFileObjectWithLocation<>(jfo, loc); 225 } 226 227 private static FileObject locWrap(FileObject fo, Location loc) { 228 if (fo instanceof JavaFileObject) 229 return locWrap((JavaFileObject) fo, loc); 230 return fo == null ? null : new FileObjectWithLocation<>(fo, loc); 231 } 232 233 @DefinedBy(Api.COMPILER) 234 @Override 235 public boolean isSameFile(FileObject a, FileObject b) { 236 return super.isSameFile(locUnwrap(a), locUnwrap(b)); 237 } 238 239 private static ListBuffer<JavaFileObject> locWrapMany(Iterable<JavaFileObject> jfos, 240 Location loc) { 241 ListBuffer<JavaFileObject> locWrapped = new ListBuffer<>(); 242 for (JavaFileObject f : jfos) 243 locWrapped.add(locWrap(f, loc)); 244 return locWrapped; 245 } 246 247 private static FileObject locUnwrap(FileObject fo) { 248 if (fo instanceof FileObjectWithLocation<?>) 249 return ((FileObjectWithLocation<?>) fo).getDelegate(); 250 if (fo instanceof JavaFileObjectWithLocation<?>) 251 return ((JavaFileObjectWithLocation<?>) fo).getDelegate(); 252 return fo; 253 } 254 255 private static JavaFileObject locUnwrap(JavaFileObject fo) { 256 if (fo instanceof JavaFileObjectWithLocation<?>) 257 return ((JavaFileObjectWithLocation<?>) fo).getDelegate(); 258 return fo; 259 } 260 }