T4241573.java revision 2942:08092deced3f
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.jdeps/com.sun.tools.classfile
29 */
30
31import com.sun.tools.classfile.Attribute;
32import com.sun.tools.classfile.ClassFile;
33import com.sun.tools.classfile.SourceFile_attribute;
34import java.io.*;
35import java.util.*;
36import java.util.jar.*;
37
38public 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}
232