cfdc64fcb4
Reviewed-by: liach, redestad, vromero
228 lines
8.1 KiB
Java
228 lines
8.1 KiB
Java
/*
|
|
* Copyright (c) 2009, 2015, 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.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 4241573
|
|
* @summary SourceFile attribute includes full path
|
|
* @enablePreview
|
|
* @modules java.base/jdk.internal.classfile.impl
|
|
*/
|
|
|
|
import java.lang.classfile.*;
|
|
import java.lang.classfile.Attributes;
|
|
import java.lang.classfile.attribute.*;
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import java.util.jar.*;
|
|
|
|
public class T4241573 {
|
|
public static void main(String... args) throws Exception {
|
|
new T4241573().run();
|
|
}
|
|
|
|
public void run() throws Exception {
|
|
// Selection of files to be compiled
|
|
File absJar = createJar(new File("abs.jar").getAbsoluteFile(), "j.A");
|
|
File relJar = createJar(new File("rel.jar"), "j.R");
|
|
File absDir = createDir(new File("abs.dir").getAbsoluteFile(), "d.A");
|
|
File relDir = createDir(new File("rel.dir"), "d.R");
|
|
File absTestFile = writeFile(new File("AbsTest.java").getAbsoluteFile(), "class AbsTest { class Inner { } }");
|
|
File relTestFile = writeFile(new File("RelTest.java"), "class RelTest { class Inner { } }");
|
|
File relTest2File = writeFile(new File("p/RelTest2.java"), "package p; class RelTest2 { class Inner { } }");
|
|
// This next class references other classes that will be found on the source path
|
|
// and which will therefore need to be compiled as well.
|
|
File mainFile = writeFile(new File("Main.java"),
|
|
"class Main { j.A ja; j.R jr; d.A da; d.R dr; }" +
|
|
"");
|
|
|
|
String sourcePath = createPath(absJar, relJar, absDir, relDir);
|
|
File outDir = new File("classes");
|
|
outDir.mkdirs();
|
|
|
|
String[] args = {
|
|
"-sourcepath", sourcePath,
|
|
"-d", outDir.getPath(),
|
|
absTestFile.getPath(),
|
|
relTestFile.getPath(),
|
|
relTest2File.getPath(),
|
|
mainFile.getPath(),
|
|
};
|
|
System.err.println("compile: " + Arrays.asList(args));
|
|
StringWriter sw = new StringWriter();
|
|
PrintWriter pw = new PrintWriter(sw);
|
|
int rc = com.sun.tools.javac.Main.compile(args, pw);
|
|
pw.close();
|
|
if (rc != 0) {
|
|
System.err.println(sw.toString());
|
|
throw new Exception("unexpected exit from javac: " + rc);
|
|
}
|
|
|
|
Set<File> expect = getFiles(outDir,
|
|
"d/A.class", "d/A$Inner.class",
|
|
"d/R.class", "d/R$Inner.class",
|
|
"j/A.class", "j/A$Inner.class",
|
|
"j/R.class", "j/R$Inner.class",
|
|
"AbsTest.class", "AbsTest$Inner.class",
|
|
"RelTest.class", "RelTest$Inner.class",
|
|
"p/RelTest2.class", "p/RelTest2$Inner.class",
|
|
"Main.class" );
|
|
|
|
Set<File> found = findFiles(outDir);
|
|
|
|
if (!found.equals(expect)) {
|
|
if (found.containsAll(expect))
|
|
throw new Exception("unexpected files found: " + diff(found, expect));
|
|
else if (expect.containsAll(found))
|
|
throw new Exception("expected files not found: " + diff(expect, found));
|
|
}
|
|
|
|
for (File f: found)
|
|
verifySourceFileAttribute(f);
|
|
|
|
if (errors > 0)
|
|
throw new Exception(errors + " errors occurred");
|
|
}
|
|
|
|
/** Check the SourceFileAttribute is the simple name of the original source file. */
|
|
void verifySourceFileAttribute(File f) {
|
|
System.err.println("verify: " + f);
|
|
try {
|
|
ClassModel cf = ClassFile.of().parse(f.toPath());
|
|
SourceFileAttribute sfa = cf.findAttribute(Attributes.sourceFile()).orElseThrow();
|
|
String found = sfa.sourceFile().stringValue();
|
|
String expect = f.getName().replaceAll("([$.].*)?\\.class", ".java");
|
|
if (!expect.equals(found)) {
|
|
error("bad value found: " + found + ", expected: " + expect);
|
|
}
|
|
} catch (Exception e) {
|
|
error("error reading " + f +": " + e);
|
|
}
|
|
}
|
|
|
|
/** Create a directory containing one or more files. */
|
|
File createDir(File dir, String... entries) throws Exception {
|
|
if (!dir.mkdirs())
|
|
throw new Exception("cannot create directories " + dir);
|
|
for (String e: entries) {
|
|
writeFile(new File(dir, getPathForDirEntry(e)), getBodyForEntry(e));
|
|
}
|
|
return dir;
|
|
}
|
|
|
|
/** Create a jar file containing one or more entries. */
|
|
File createJar(File jar, String... entries) throws IOException {
|
|
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(jar))) {
|
|
for (String e: entries) {
|
|
jos.putNextEntry(new JarEntry(getPathForZipEntry(e)));
|
|
jos.write(getBodyForEntry(e).getBytes());
|
|
}
|
|
}
|
|
return jar;
|
|
}
|
|
|
|
/** Return the path for an entry given to createDir */
|
|
String getPathForDirEntry(String e) {
|
|
return e.replace(".", File.separator) + ".java";
|
|
}
|
|
|
|
/** Return the path for an entry given to createJar. */
|
|
String getPathForZipEntry(String e) {
|
|
return e.replace(".", "/") + ".java";
|
|
}
|
|
|
|
/** Return the body text for an entry given to createDir or createJar. */
|
|
String getBodyForEntry(String e) {
|
|
int sep = e.lastIndexOf(".");
|
|
String pkgName = e.substring(0, sep);
|
|
String className = e.substring(sep + 1);
|
|
return "package " + pkgName + "; public class " + className + "{ class Inner { } }";
|
|
}
|
|
|
|
/** Write a file containing the given string. Parent directories are
|
|
* created as needed. */
|
|
File writeFile(File f, String s) throws IOException {
|
|
if (f.getParentFile() != null)
|
|
f.getParentFile().mkdirs();
|
|
FileWriter out = new FileWriter(f);
|
|
try {
|
|
out.write(s);
|
|
} finally {
|
|
out.close();
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/** Create a path value from a list of directories and jar files. */
|
|
String createPath(File... files) {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (File f: files) {
|
|
if (sb.length() > 0)
|
|
sb.append(File.pathSeparatorChar);
|
|
sb.append(f.getPath());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
/** Create a set of files from a base directory and a set of relative paths. */
|
|
Set<File> getFiles(File dir, String... paths) {
|
|
Set<File> files = new LinkedHashSet<File>();
|
|
for (String p: paths)
|
|
files.add(new File(dir, p));
|
|
return files;
|
|
}
|
|
|
|
/** Find all the files in a directory and its subdirectories. */
|
|
Set<File> findFiles(File dir) {
|
|
Set<File> files = new LinkedHashSet<File>();
|
|
findFiles(dir, files);
|
|
return files;
|
|
}
|
|
// where
|
|
void findFiles(File dir, Set<File> files) {
|
|
for (File f: dir.listFiles()) {
|
|
if (f.isDirectory())
|
|
findFiles(f, files);
|
|
else
|
|
files.add(f);
|
|
}
|
|
}
|
|
|
|
/** Return the difference of two sets, a - b. */
|
|
<T> Set<T> diff(Set<T> a, Set<T> b) {
|
|
if (b.isEmpty())
|
|
return a;
|
|
Set<T> result = new LinkedHashSet<T>(a);
|
|
result.removeAll(b);
|
|
return result;
|
|
}
|
|
|
|
/** Report an error. */
|
|
void error(String msg) {
|
|
System.err.println(msg);
|
|
errors++;
|
|
}
|
|
|
|
int errors;
|
|
}
|