1 /* 2 * Copyright (c) 2009, 2015, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 4241573 27 * @summary SourceFile attribute includes full path 28 * @modules jdk.compiler/com.sun.tools.classfile 29 */ 30 31 import com.sun.tools.classfile.Attribute; 32 import com.sun.tools.classfile.ClassFile; 33 import com.sun.tools.classfile.SourceFile_attribute; 34 import java.io.*; 35 import java.util.*; 36 import java.util.jar.*; 37 38 public class T4241573 { 39 public static void main(String... args) throws Exception { 40 new T4241573().run(); 41 } 42 43 public void run() throws Exception { 44 // Selection of files to be compiled 45 File absJar = createJar(new File("abs.jar").getAbsoluteFile(), "j.A"); 46 File relJar = createJar(new File("rel.jar"), "j.R"); 47 File absDir = createDir(new File("abs.dir").getAbsoluteFile(), "d.A"); 48 File relDir = createDir(new File("rel.dir"), "d.R"); 49 File absTestFile = writeFile(new File("AbsTest.java").getAbsoluteFile(), "class AbsTest { class Inner { } }"); 50 File relTestFile = writeFile(new File("RelTest.java"), "class RelTest { class Inner { } }"); 51 File relTest2File = writeFile(new File("p/RelTest2.java"), "package p; class RelTest2 { class Inner { } }"); 52 // This next class references other classes that will be found on the source path 53 // and which will therefore need to be compiled as well. 54 File mainFile = writeFile(new File("Main.java"), 55 "class Main { j.A ja; j.R jr; d.A da; d.R dr; }" + 56 ""); 57 58 String sourcePath = createPath(absJar, relJar, absDir, relDir); 59 File outDir = new File("classes"); 60 outDir.mkdirs(); 61 62 String[] args = { 63 "-sourcepath", sourcePath, 64 "-d", outDir.getPath(), 65 absTestFile.getPath(), 66 relTestFile.getPath(), 67 relTest2File.getPath(), 68 mainFile.getPath(), 69 }; 70 System.err.println("compile: " + Arrays.asList(args)); 71 StringWriter sw = new StringWriter(); 72 PrintWriter pw = new PrintWriter(sw); 73 int rc = com.sun.tools.javac.Main.compile(args, pw); 74 pw.close(); 75 if (rc != 0) { 76 System.err.println(sw.toString()); 77 throw new Exception("unexpected exit from javac: " + rc); 78 } 79 80 Set<File> expect = getFiles(outDir, 81 "d/A.class", "d/A$Inner.class", 82 "d/R.class", "d/R$Inner.class", 83 "j/A.class", "j/A$Inner.class", 84 "j/R.class", "j/R$Inner.class", 85 "AbsTest.class", "AbsTest$Inner.class", 86 "RelTest.class", "RelTest$Inner.class", 87 "p/RelTest2.class", "p/RelTest2$Inner.class", 88 "Main.class" ); 89 90 Set<File> found = findFiles(outDir); 91 92 if (!found.equals(expect)) { 93 if (found.containsAll(expect)) 94 throw new Exception("unexpected files found: " + diff(found, expect)); 95 else if (expect.containsAll(found)) 96 throw new Exception("expected files not found: " + diff(expect, found)); 97 } 98 99 for (File f: found) 100 verifySourceFileAttribute(f); 101 102 if (errors > 0) 103 throw new Exception(errors + " errors occurred"); 104 } 105 106 /** Check the SourceFileAttribute is the simple name of the original source file. */ 107 void verifySourceFileAttribute(File f) { 108 System.err.println("verify: " + f); 109 try { 110 ClassFile cf = ClassFile.read(f); 111 SourceFile_attribute sfa = (SourceFile_attribute) cf.getAttribute(Attribute.SourceFile); 112 String found = sfa.getSourceFile(cf.constant_pool); 113 String expect = f.getName().replaceAll("([$.].*)?\\.class", ".java"); 114 if (!expect.equals(found)) { 115 error("bad value found: " + found + ", expected: " + expect); 116 } 117 } catch (Exception e) { 118 error("error reading " + f +": " + e); 119 } 120 } 121 122 /** Create a directory containing one or more files. */ 123 File createDir(File dir, String... entries) throws Exception { 124 if (!dir.mkdirs()) 125 throw new Exception("cannot create directories " + dir); 126 for (String e: entries) { 127 writeFile(new File(dir, getPathForDirEntry(e)), getBodyForEntry(e)); 128 } 129 return dir; 130 } 131 132 /** Create a jar file containing one or more entries. */ 133 File createJar(File jar, String... entries) throws IOException { 134 OutputStream out = new FileOutputStream(jar); 135 try { 136 JarOutputStream jos = new JarOutputStream(out); 137 for (String e: entries) { 138 jos.putNextEntry(new JarEntry(getPathForZipEntry(e))); 139 jos.write(getBodyForEntry(e).getBytes()); 140 } 141 jos.close(); 142 } finally { 143 out.close(); 144 } 145 return jar; 146 } 147 148 /** Return the path for an entry given to createDir */ 149 String getPathForDirEntry(String e) { 150 return e.replace(".", File.separator) + ".java"; 151 } 152 153 /** Return the path for an entry given to createJar. */ 154 String getPathForZipEntry(String e) { 155 return e.replace(".", "/") + ".java"; 156 } 157 158 /** Return the body text for an entry given to createDir or createJar. */ 159 String getBodyForEntry(String e) { 160 int sep = e.lastIndexOf("."); 161 String pkgName = e.substring(0, sep); 162 String className = e.substring(sep + 1); 163 return "package " + pkgName + "; public class " + className + "{ class Inner { } }"; 164 } 165 166 /** Write a file containing the given string. Parent directories are 167 * created as needed. */ 168 File writeFile(File f, String s) throws IOException { 169 if (f.getParentFile() != null) 170 f.getParentFile().mkdirs(); 171 FileWriter out = new FileWriter(f); 172 try { 173 out.write(s); 174 } finally { 175 out.close(); 176 } 177 return f; 178 } 179 180 /** Create a path value from a list of directories and jar files. */ 181 String createPath(File... files) { 182 StringBuilder sb = new StringBuilder(); 183 for (File f: files) { 184 if (sb.length() > 0) 185 sb.append(File.pathSeparatorChar); 186 sb.append(f.getPath()); 187 } 188 return sb.toString(); 189 } 190 191 /** Create a set of files from a base directory and a set of relative paths. */ 192 Set<File> getFiles(File dir, String... paths) { 193 Set<File> files = new LinkedHashSet<File>(); 194 for (String p: paths) 195 files.add(new File(dir, p)); 196 return files; 197 } 198 199 /** Find all the files in a directory and its subdirectories. */ 200 Set<File> findFiles(File dir) { 201 Set<File> files = new LinkedHashSet<File>(); 202 findFiles(dir, files); 203 return files; 204 } 205 // where 206 void findFiles(File dir, Set<File> files) { 207 for (File f: dir.listFiles()) { 208 if (f.isDirectory()) 209 findFiles(f, files); 210 else 211 files.add(f); 212 } 213 } 214 215 /** Return the difference of two sets, a - b. */ 216 <T> Set<T> diff(Set<T> a, Set<T> b) { 217 if (b.isEmpty()) 218 return a; 219 Set<T> result = new LinkedHashSet<T>(a); 220 result.removeAll(b); 221 return result; 222 } 223 224 /** Report an error. */ 225 void error(String msg) { 226 System.err.println(msg); 227 errors++; 228 } 229 230 int errors; 231 }