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