SmartFileManager.java revision 2593:035b01d356ee
1107571Sgrehan/* 2107571Sgrehan * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 3107571Sgrehan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4107571Sgrehan * 5107571Sgrehan * This code is free software; you can redistribute it and/or modify it 6107571Sgrehan * under the terms of the GNU General Public License version 2 only, as 7107571Sgrehan * published by the Free Software Foundation. Oracle designates this 8107571Sgrehan * particular file as subject to the "Classpath" exception as provided 9107571Sgrehan * by Oracle in the LICENSE file that accompanied this code. 10107571Sgrehan * 11107571Sgrehan * This code is distributed in the hope that it will be useful, but WITHOUT 12107571Sgrehan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13107571Sgrehan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14107571Sgrehan * version 2 for more details (a copy is included in the LICENSE file that 15107571Sgrehan * accompanied this code). 16107571Sgrehan * 17107571Sgrehan * You should have received a copy of the GNU General Public License version 18107571Sgrehan * 2 along with this work; if not, write to the Free Software Foundation, 19107571Sgrehan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20107571Sgrehan * 21107571Sgrehan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22107571Sgrehan * or visit www.oracle.com if you need additional information or have any 23107571Sgrehan * questions. 24107571Sgrehan */ 25107571Sgrehan 26107571Sgrehanpackage com.sun.tools.sjavac.comp; 27107571Sgrehan 28107571Sgrehanimport java.io.IOException; 29107571Sgrehanimport java.io.PrintWriter; 30107571Sgrehanimport java.net.URI; 31107571Sgrehanimport java.util.HashMap; 32107571Sgrehanimport java.util.HashSet; 33107571Sgrehanimport java.util.Map; 34107571Sgrehanimport java.util.Set; 35107571Sgrehan 36107571Sgrehanimport javax.tools.*; 37107571Sgrehanimport javax.tools.JavaFileObject.Kind; 38107571Sgrehan 39107571Sgrehanimport com.sun.tools.javac.file.JavacFileManager; 40107571Sgrehanimport com.sun.tools.javac.util.ListBuffer; 41107571Sgrehan 42107571Sgrehan/** 43107571Sgrehan * Intercepts reads and writes to the file system to gather 44107571Sgrehan * information about what artifacts are generated. 45107571Sgrehan * 46107571Sgrehan * Traps writes to certain files, if the content written is identical 47107571Sgrehan * to the existing file. 48107571Sgrehan * 49107571Sgrehan * Can also blind out the filemanager from seeing certain files in the file system. 50107571Sgrehan * Necessary to prevent javac from seeing some sources where the source path points. 51107571Sgrehan * 52107571Sgrehan * <p><b>This is NOT part of any supported API. 53107571Sgrehan * If you write code that depends on this, you do so at your own risk. 54107571Sgrehan * This code and its internal interfaces are subject to change or 55107571Sgrehan * deletion without notice.</b> 56107571Sgrehan */ 57107571Sgrehanpublic class SmartFileManager extends ForwardingJavaFileManager<JavaFileManager> { 58107571Sgrehan 59107571Sgrehan // Set of sources that can be seen by javac. 60107571Sgrehan Set<URI> visibleSources = new HashSet<>(); 61107571Sgrehan // Map from modulename:packagename to artifacts. 62107571Sgrehan Map<String,Set<URI>> packageArtifacts = new HashMap<>(); 63107571Sgrehan // Where to print informational messages. 64107571Sgrehan PrintWriter stdout; 65107571Sgrehan 66107571Sgrehan public SmartFileManager(JavaFileManager fileManager) { 67107571Sgrehan super(fileManager); 68107571Sgrehan } 69107571Sgrehan 70107571Sgrehan public void setVisibleSources(Set<URI> s) { 71107571Sgrehan visibleSources = s; 72107571Sgrehan } 73107571Sgrehan 74 public void cleanArtifacts() { 75 packageArtifacts = new HashMap<>(); 76 } 77 78 public void setLog(PrintWriter pw) { 79 stdout = pw; 80 } 81 82 /** 83 * Set whether or not to use ct.sym as an alternate to rt.jar. 84 */ 85 public void setSymbolFileEnabled(boolean b) { 86 if (!(fileManager instanceof JavacFileManager)) 87 throw new IllegalStateException(); 88 ((JavacFileManager) fileManager).setSymbolFileEnabled(b); 89 } 90 91 public Map<String,Set<URI>> getPackageArtifacts() { 92 return packageArtifacts; 93 } 94 95 @Override 96 public Iterable<JavaFileObject> list(Location location, 97 String packageName, 98 Set<Kind> kinds, 99 boolean recurse) throws IOException { 100 // Acquire the list of files. 101 Iterable<JavaFileObject> files = super.list(location, packageName, kinds, recurse); 102 if (visibleSources.isEmpty()) { 103 return files; 104 } 105 // Now filter! 106 ListBuffer<JavaFileObject> filteredFiles = new ListBuffer<>(); 107 for (JavaFileObject f : files) { 108 URI uri = f.toUri(); 109 String t = uri.toString(); 110 if (t.startsWith("jar:") 111 || t.endsWith(".class") 112 || visibleSources.contains(uri)) { 113 filteredFiles.add(f); 114 } 115 } 116 return filteredFiles; 117 } 118 119 @Override 120 public boolean hasLocation(Location location) { 121 return super.hasLocation(location); 122 } 123 124 @Override 125 public JavaFileObject getJavaFileForInput(Location location, 126 String className, 127 Kind kind) throws IOException { 128 JavaFileObject file = super.getJavaFileForInput(location, className, kind); 129 if (file == null || visibleSources.isEmpty()) { 130 return file; 131 } 132 133 if (visibleSources.contains(file.toUri())) { 134 return file; 135 } 136 return null; 137 } 138 139 @Override 140 public JavaFileObject getJavaFileForOutput(Location location, 141 String className, 142 Kind kind, 143 FileObject sibling) throws IOException { 144 JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); 145 if (file == null) return file; 146 int dp = className.lastIndexOf('.'); 147 String pkg_name = ""; 148 if (dp != -1) { 149 pkg_name = className.substring(0, dp); 150 } 151 // When modules are in use, then the mod_name might be something like "jdk_base" 152 String mod_name = ""; 153 addArtifact(mod_name+":"+pkg_name, file.toUri()); 154 return file; 155 } 156 157 @Override 158 public FileObject getFileForInput(Location location, 159 String packageName, 160 String relativeName) throws IOException { 161 FileObject file = super.getFileForInput(location, packageName, relativeName); 162 if (file == null || visibleSources.isEmpty()) { 163 return file; 164 } 165 166 if (visibleSources.contains(file.toUri())) { 167 return file; 168 } 169 return null; 170 } 171 172 @Override 173 public FileObject getFileForOutput(Location location, 174 String packageName, 175 String relativeName, 176 FileObject sibling) throws IOException { 177 FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling); 178 if (file == null) return file; 179 if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && 180 file instanceof JavaFileObject) { 181 file = new SmartFileObject((JavaFileObject)file, stdout); 182 packageName = ":" + packageNameFromFileName(relativeName); 183 } 184 if (packageName.equals("")) { 185 packageName = ":"; 186 } 187 addArtifact(packageName, file.toUri()); 188 return file; 189 } 190 191 private String packageNameFromFileName(String fn) { 192 StringBuilder sb = new StringBuilder(); 193 int p = fn.indexOf('_'), pp = 0; 194 while (p != -1) { 195 if (sb.length() > 0) sb.append('.'); 196 sb.append(fn.substring(pp,p)); 197 if (p == fn.length()-1) break; 198 pp = p+1; 199 p = fn.indexOf('_',pp); 200 } 201 return sb.toString(); 202 } 203 204 @Override 205 public void flush() throws IOException { 206 super.flush(); 207 } 208 209 @Override 210 public void close() throws IOException { 211 super.close(); 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