feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import javax.lang.model.element.Element;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
/** Utility class containing dependency information between packages
* and the pubapi for a package.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class Dependencies {
protected static final Context.Key<Dependencies> dependenciesKey =
new Context.Key<Dependencies>();
// The log to be used for error reporting.
protected Log log;
// Map from package name to packages that the package depends upon.
protected Map<Name,Set<Name>> deps;
// This is the set of all packages that are supplied
// through the java files at the command line.
protected Set<Name> explicitPackages;
// Map from a package name to its public api.
// Will the Name encode the module in the future?
// If not, this will have to change to map from Module+Name to public api.
protected Map<Name,StringBuffer> publicApiPerClass;
public static Dependencies instance(Context context) {
Dependencies instance = context.get(dependenciesKey);
if (instance == null)
instance = new Dependencies(context);
return instance;
}
private Dependencies(Context context) {
context.put(dependenciesKey, this);
log = Log.instance(context);
}
public void reset()
{
deps = new HashMap<Name, Set<Name>>();
explicitPackages = new HashSet<Name>();
publicApiPerClass = new HashMap<Name,StringBuffer>();
}
/**
* Fetch the set of dependencies that are relevant to the compile
* that has just been performed. I.e. we are only interested in
* dependencies for classes that were explicitly compiled.
* @return
*/
public Map<String,Set<String>> getDependencies() {
Map<String,Set<String>> new_deps = new HashMap<String,Set<String>>();
if (explicitPackages == null) return new_deps;
for (Name pkg : explicitPackages) {
Set<Name> set = deps.get(pkg);
if (set != null) {
Set<String> new_set = new_deps.get(pkg.toString());
if (new_set == null) {
new_set = new HashSet<String>();
// Modules beware....
new_deps.put(":"+pkg.toString(), new_set);
}
for (Name d : set) {
new_set.add(":"+d.toString());
}
}
}
return new_deps;
}
static class CompareNames implements Comparator<Name> {
public int compare(Name a, Name b) {
return a.toString().compareTo(b.toString());
}
}
/**
* Convert the map from class names to their pubapi to a map
* from package names to their pubapi (which is the sorted concatenation
* of all the class pubapis)
*/
public Map<String,String> getPubapis() {
Map<String,String> publicApiPerPackage = new HashMap<String,String>();
if (publicApiPerClass == null) return publicApiPerPackage;
Name[] keys = publicApiPerClass.keySet().toArray(new Name[0]);
Arrays.sort(keys, new CompareNames());
StringBuffer newPublicApi = new StringBuffer();
int i=0;
String prevPkg = "";
for (Name k : keys) {
String cn = k.toString();
String pn = "";
int dp = cn.lastIndexOf('.');
if (dp != -1) {
pn = cn.substring(0,dp);
}
if (!pn.equals(prevPkg)) {
if (!prevPkg.equals("")) {
// Add default module name ":"
publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
}
newPublicApi = new StringBuffer();
prevPkg = pn;
}
newPublicApi.append(publicApiPerClass.get(k));
i++;
}
if (!prevPkg.equals(""))
publicApiPerPackage.put(":"+prevPkg, newPublicApi.toString());
return publicApiPerPackage;
}
/**
* Visit the api of a class and construct a pubapi string and
* store it into the pubapi_perclass map.
*/
public void visitPubapi(Element e) {
Name n = ((ClassSymbol)e).fullname;
Name p = ((ClassSymbol)e).packge().fullname;
StringBuffer sb = publicApiPerClass.get(n);
assert(sb == null);
sb = new StringBuffer();
PubapiVisitor v = new PubapiVisitor(sb);
v.visit(e);
if (sb.length()>0) {
publicApiPerClass.put(n, sb);
}
explicitPackages.add(p);
}
/**
* Collect a dependency. curr_pkg is marked as depending on dep_pkg.
*/
public void collect(Name currPkg, Name depPkg) {
if (!currPkg.equals(depPkg)) {
Set<Name> theset = deps.get(currPkg);
if (theset==null) {
theset = new HashSet<Name>();
deps.put(currPkg, theset);
}
theset.add(depPkg);
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import java.util.StringTokenizer;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.sjavac.server.CompilerThread;
import java.io.File;
/** Subclass to Resolve that overrides collect.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class JavaCompilerWithDeps extends JavaCompiler {
/** The dependency database
*/
protected Dependencies deps;
protected CompilerThread compilerThread;
public JavaCompilerWithDeps(Context context, CompilerThread t) {
super(context);
deps = Dependencies.instance(context);
compilerThread = t;
needRootClasses = true;
}
public static void preRegister(Context context, final CompilerThread t) {
context.put(compilerKey, new Context.Factory<JavaCompiler>() {
public JavaCompiler make(Context c) {
JavaCompiler instance = new JavaCompilerWithDeps(c, t);
c.put(JavaCompiler.class, instance);
return instance;
}
});
}
/** Collect the public apis of classes supplied explicitly for compilation.
* @param sym The class to visit.
*/
@Override
public void reportPublicApi(ClassSymbol sym) {
// The next test will catch when source files are located in the wrong directory!
// This ought to be moved into javac as a new warning, or perhaps as part
// of the auxiliary class warning.
// For example if sun.swing.BeanInfoUtils
// is in fact stored in: /mybuild/jdk/gensrc/javax/swing/beaninfo/BeanInfoUtils.java
// We do not need to test that BeanInfoUtils is stored in a file named BeanInfoUtils
// since this is checked earlier.
if (sym.sourcefile != null) {
// Rewrite sun.swing.BeanInfoUtils into /sun/swing/
StringBuilder pathb = new StringBuilder();
StringTokenizer qn = new StringTokenizer(sym.packge().toString(), ".");
boolean first = true;
while (qn.hasMoreTokens()) {
String o = qn.nextToken();
pathb.append("/");
pathb.append(o);
first = false;
}
pathb.append("/");
String path = pathb.toString();
// Now cut the uri to be: file:///mybuild/jdk/gensrc/javax/swing/beaninfo/
String p = sym.sourcefile.toUri().getPath();
// Do not use File.separatorChar here, a URI always uses slashes /.
int i = p.lastIndexOf("/");
String pp = p.substring(0,i+1);
// Now check if the truncated uri ends with the path. (It does not == failure!)
if (path.length() > 0 && !path.equals("/unnamed package/") && !pp.endsWith(path)) {
compilerThread.logError("Error: The source file "+sym.sourcefile.getName()+
" is located in the wrong package directory, because it contains the class "+
sym.getQualifiedName());
}
}
deps.visitPubapi(sym);
}
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import java.util.Iterator;
import java.util.List;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementScanner6;
/** Utility class that constructs a textual representation
* of the public api of a class.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class PubapiVisitor extends ElementScanner6<Void, Void> {
StringBuffer sb;
// Important that it is 1! Part of protocol over wire, silly yes.
// Fix please.
int indent = 1;
public PubapiVisitor(StringBuffer sb) {
this.sb = sb;
}
String depth(int l) {
return " ".substring(0, l);
}
@Override
public Void visitType(TypeElement e, Void p) {
if (e.getModifiers().contains(Modifier.PUBLIC)
|| e.getModifiers().contains(Modifier.PROTECTED))
{
sb.append(depth(indent) + "TYPE " + e.getQualifiedName() + "\n");
indent += 2;
Void v = super.visitType(e, p);
indent -= 2;
return v;
}
return null;
}
@Override
public Void visitVariable(VariableElement e, Void p) {
if (e.getModifiers().contains(Modifier.PUBLIC)
|| e.getModifiers().contains(Modifier.PROTECTED)) {
sb.append(depth(indent)).append("VAR ")
.append(makeVariableString(e)).append("\n");
}
// Safe to not recurse here, because the only thing
// to visit here is the constructor of a variable declaration.
// If it happens to contain an anonymous inner class (which it might)
// then this class is never visible outside of the package anyway, so
// we are allowed to ignore it here.
return null;
}
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
if (e.getModifiers().contains(Modifier.PUBLIC)
|| e.getModifiers().contains(Modifier.PROTECTED)) {
sb.append(depth(indent)).append("METHOD ")
.append(makeMethodString(e)).append("\n");
}
return null;
}
/**
* Creates a String representation of a method element with everything
* necessary to track all public aspects of it in an API.
* @param e Element to create String for.
* @return String representation of element.
*/
protected String makeMethodString(ExecutableElement e) {
StringBuilder result = new StringBuilder();
for (Modifier modifier : e.getModifiers()) {
result.append(modifier.toString());
result.append(" ");
}
result.append(e.getReturnType().toString());
result.append(" ");
result.append(e.toString());
List<? extends TypeMirror> thrownTypes = e.getThrownTypes();
if (!thrownTypes.isEmpty()) {
result.append(" throws ");
for (Iterator<? extends TypeMirror> iterator = thrownTypes
.iterator(); iterator.hasNext();) {
TypeMirror typeMirror = iterator.next();
result.append(typeMirror.toString());
if (iterator.hasNext()) {
result.append(", ");
}
}
}
return result.toString();
}
/**
* Creates a String representation of a variable element with everything
* necessary to track all public aspects of it in an API.
* @param e Element to create String for.
* @return String representation of element.
*/
protected String makeVariableString(VariableElement e) {
StringBuilder result = new StringBuilder();
for (Modifier modifier : e.getModifiers()) {
result.append(modifier.toString());
result.append(" ");
}
result.append(e.asType().toString());
result.append(" ");
result.append(e.toString());
Object value = e.getConstantValue();
if (value != null) {
result.append(" = ");
if (e.asType().toString().equals("char")) {
int v = (int)value.toString().charAt(0);
result.append("'\\u"+Integer.toString(v,16)+"'");
} else {
result.append(value.toString());
}
}
return result.toString();
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.code.Symbol;
/** Subclass to Resolve that overrides collect.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class ResolveWithDeps extends Resolve {
/** The dependency database
*/
protected Dependencies deps;
protected ResolveWithDeps(Context context) {
super(context);
deps = Dependencies.instance(context);
}
public static void preRegister(Context context) {
context.put(resolveKey, new Context.Factory<Resolve>() {
public Resolve make(Context c) {
Resolve instance = new ResolveWithDeps(c);
c.put(Resolve.class, instance);
return instance;
}
});
}
/** Collect dependencies in the enclosing class
* @param from The enclosing class sym
* @param to The enclosing classes references this sym.
* */
@Override
public void reportDependence(Symbol from, Symbol to) {
// Capture dependencies between the packages.
deps.collect(from.packge().fullname, to.packge().fullname);
}
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import com.sun.tools.javac.util.ListBuffer;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
/**
* Intercepts reads and writes to the file system to gather
* information about what artifacts are generated.
*
* Traps writes to certain files, if the content written is identical
* to the existing file.
*
* Can also blind out the filemanager from seeing certain files in the file system.
* Necessary to prevent javac from seeing some sources where the source path points.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class SmartFileManager extends ForwardingJavaFileManager<JavaFileManager> {
// Set of sources that can be seen by javac.
Set<URI> visibleSources = new HashSet<URI>();
// Map from modulename:packagename to artifacts.
Map<String,Set<URI>> packageArtifacts = new HashMap<String,Set<URI>>();
// Where to print informational messages.
PrintWriter stdout;
public SmartFileManager(JavaFileManager fileManager) {
super(fileManager);
}
public void setVisibleSources(Set<URI> s) {
visibleSources = s;
}
public void cleanArtifacts() {
packageArtifacts = new HashMap<String,Set<URI>>();
}
public void setLog(PrintWriter pw) {
stdout = pw;
}
public Map<String,Set<URI>> getPackageArtifacts() {
return packageArtifacts;
}
@Override
public Iterable<JavaFileObject> list(Location location,
String packageName,
Set<Kind> kinds,
boolean recurse)
throws IOException
{
// Acquire the list of files.
Iterable<JavaFileObject> files = super.list(location, packageName, kinds, recurse);
if (visibleSources.isEmpty()) {
return files;
}
// Now filter!
ListBuffer<JavaFileObject> filteredFiles = new ListBuffer<JavaFileObject>();
for (JavaFileObject f : files) {
URI uri = f.toUri();
String t = uri.toString();
if (t.startsWith("jar:")
|| t.endsWith(".class")
|| visibleSources.contains(uri))
{
filteredFiles.add(f);
}
}
return filteredFiles;
}
@Override
public boolean hasLocation(Location location) {
return super.hasLocation(location);
}
@Override
public JavaFileObject getJavaFileForInput(Location location,
String className,
Kind kind)
throws IOException
{
JavaFileObject file = super.getJavaFileForInput(location, className, kind);
if (file == null || visibleSources.isEmpty()) {
return file;
}
if (visibleSources.contains(file.toUri())) {
return file;
}
return null;
}
@Override
public JavaFileObject getJavaFileForOutput(Location location,
String className,
Kind kind,
FileObject sibling)
throws IOException
{
JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling);
if (file == null) return file;
int dp = className.lastIndexOf('.');
String pkg_name = "";
if (dp != -1) {
pkg_name = className.substring(0, dp);
}
// When modules are in use, then the mod_name might be something like "jdk_base"
String mod_name = "";
addArtifact(mod_name+":"+pkg_name, file.toUri());
return file;
}
@Override
public FileObject getFileForInput(Location location,
String packageName,
String relativeName)
throws IOException
{
FileObject file = super.getFileForInput(location, packageName, relativeName);
if (file == null || visibleSources.isEmpty()) {
return file;
}
if (visibleSources.contains(file.toUri())) {
return file;
}
return null;
}
@Override
public FileObject getFileForOutput(Location location,
String packageName,
String relativeName,
FileObject sibling)
throws IOException
{
FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling);
if (file == null) return file;
if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) &&
file instanceof JavaFileObject) {
file = new SmartFileObject((JavaFileObject)file, stdout);
packageName = ":" + packageNameFromFileName(relativeName);
}
if (packageName.equals("")) {
packageName = ":";
}
addArtifact(packageName, file.toUri());
return file;
}
private String packageNameFromFileName(String fn) {
StringBuilder sb = new StringBuilder();
int p = fn.indexOf('_'), pp = 0;
while (p != -1) {
if (sb.length() > 0) sb.append('.');
sb.append(fn.substring(pp,p));
if (p == fn.length()-1) break;
pp = p+1;
p = fn.indexOf('_',pp);
}
return sb.toString();
}
@Override
public void flush() throws IOException {
super.flush();
}
@Override
public void close() throws IOException {
super.close();
}
void addArtifact(String pkgName, URI art) {
Set<URI> s = packageArtifacts.get(pkgName);
if (s == null) {
s = new HashSet<URI>();
packageArtifacts.put(pkgName, s);
}
s.add(art);
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import java.io.*;
import java.net.URI;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.JavaFileObject;
/**
* The SmartFileObject will return an outputstream that cache the written data
* and compare the new content with the old content on disk. Only if they differ,
* will the file be updated.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class SmartFileObject implements JavaFileObject {
JavaFileObject file;
PrintWriter stdout;
public SmartFileObject(JavaFileObject r, PrintWriter pw) {
file = r;
stdout = pw;
}
@Override
public boolean equals(Object other) {
return file.equals(other);
}
@Override
public int hashCode() {
return file.hashCode();
}
public Kind getKind() {
return file.getKind();
}
public boolean isNameCompatible(String simpleName, Kind kind) {
return file.isNameCompatible(simpleName, kind);
}
public URI toUri() {
return file.toUri();
}
public String getName() {
return file.getName();
}
public InputStream openInputStream() throws IOException {
return file.openInputStream();
}
public OutputStream openOutputStream() throws IOException {
return file.openOutputStream();
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return file.getCharContent(ignoreEncodingErrors);
}
static String lineseparator = System.getProperty("line.separator");
public Writer openWriter() throws IOException {
StringBuilder s = new StringBuilder();
try (BufferedReader r = new BufferedReader(file.openReader(true))) {
while (r.ready()) {
s.append(r.readLine()+lineseparator);
}
} catch (FileNotFoundException e) {
// Perfectly ok.
}
return new SmartWriter(file, s.toString(), file.getName(), stdout);
}
public long getLastModified() {
return file.getLastModified();
}
public boolean delete() {
return file.delete();
}
public Modifier getAccessLevel() {
return file.getAccessLevel();
}
public NestingKind getNestingKind() {
return file.getNestingKind();
}
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
return file.openReader(ignoreEncodingErrors);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.comp;
import java.io.*;
import javax.tools.JavaFileObject;
/**
* The SmartWriter will cache the written data and when the writer is closed,
* then it will compare the cached data with the old_content string.
* If different, then it will write all the new content to the file.
* If not, the file is not touched.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
public class SmartWriter extends Writer {
String name;
JavaFileObject file;
String oldContent;
StringWriter newContent = new StringWriter();
PrintWriter stdout;
boolean closed;
public SmartWriter(JavaFileObject f, String s, String n, PrintWriter pw) {
name = n;
file = f;
oldContent = s;
newContent = new StringWriter();
stdout = pw;
closed = false;
}
public void write(char[] chars, int i, int i1)
{
newContent.write(chars, i, i1);
}
public void close() throws IOException {
if (closed) return;
closed = true;
String s = newContent.toString();
if (!oldContent.equals(s)) {
int p = file.getName().lastIndexOf(File.separatorChar);
try (Writer writer = file.openWriter()) {
writer.write(s);
}
stdout.println("Writing "+file.getName().substring(p+1));
}
}
public void flush() throws IOException {
}
}