ExplodedImage.java revision 2826:c40f54b4d890
1/*
2 * Copyright (c) 2014, 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
24import com.sun.source.util.JavacTask;
25import com.sun.tools.javac.code.Symbol.ClassSymbol;
26import java.io.File;
27import java.io.IOException;
28import java.io.InputStream;
29import java.net.URI;
30import java.nio.file.DirectoryStream;
31import java.nio.file.FileSystems;
32import java.nio.file.Files;
33import java.nio.file.Path;
34import java.util.Arrays;
35import java.util.EnumSet;
36import java.util.List;
37import javax.lang.model.element.TypeElement;
38import javax.tools.Diagnostic;
39import javax.tools.DiagnosticListener;
40import javax.tools.JavaCompiler;
41import javax.tools.JavaFileObject;
42import javax.tools.StandardJavaFileManager;
43import javax.tools.StandardLocation;
44import javax.tools.ToolProvider;
45
46/**
47 * @test
48 * @bug 8067138
49 * @summary Verify that compiling against the exploded JDK image works, and that Locations close
50 *          the directory streams properly when working with exploded JDK image.
51 * @library /tools/lib
52 * @build ToolBox ExplodedImage
53 * @run main ExplodedImage
54 */
55
56public class ExplodedImage {
57    public static void main(String... args) throws IOException {
58        new ExplodedImage().run();
59    }
60
61    void run() throws IOException {
62        for (String moduleLocations : new String[] {"modules/*"}) {
63            System.setProperty("java.home", originalJavaHome);
64            testDirectoryStreamClosed(moduleLocations);
65            System.setProperty("java.home", originalJavaHome);
66            testCanCompileAgainstExplodedImage(moduleLocations);
67        }
68    }
69
70    void testDirectoryStreamClosed(String loc) throws IOException {
71        System.err.println("testDirectoryStreamClosed(" + loc + ")");
72        Path javaHome = prepareJavaHome();
73        Path targetPath = javaHome.resolve(loc.replace("*", "/java.base").replace("/", sep));
74        Path testClass = targetPath.resolve(("java/lang/" + TEST_FILE).replace("/", sep));
75        Files.createDirectories(testClass.getParent());
76        Files.createFile(testClass);
77        System.setProperty("java.home", javaHome.toString());
78
79        for (int i = 0; i < REPEATS; i++) {
80            try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
81                Iterable<JavaFileObject> javaLangContent =
82                        fm.list(StandardLocation.PLATFORM_CLASS_PATH,
83                                "java.lang",
84                                EnumSet.allOf(JavaFileObject.Kind.class),
85                                false);
86                boolean found = false;
87
88                for (JavaFileObject fo : javaLangContent) {
89                    if (!fo.getName().endsWith(TEST_FILE)) {
90                        throw new IllegalStateException("Wrong file: " + fo);
91                    }
92                    found = true;
93                }
94
95                if (!found)
96                    throw new IllegalStateException("Could not find the expected file!");
97            }
98        }
99
100        System.err.println("finished.");
101    }
102    //where:
103        static final String TEST_FILE = "ExplodedImageTestFile.class";
104        static final int REPEATS = 16 * 1024 + 1;
105
106    void testCanCompileAgainstExplodedImage(String loc) throws IOException {
107        System.err.println("testCanCompileAgainstExplodedImage(" + loc + ")");
108        Path javaHome = prepareJavaHome();
109        Path targetPath = javaHome.resolve(loc.replace("*", "/java.base").replace("/", sep));
110        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
111            for (String pack : REQUIRED_PACKAGES) {
112                Iterable<JavaFileObject> content = fm.list(StandardLocation.PLATFORM_CLASS_PATH,
113                                                           pack,
114                                                           EnumSet.allOf(JavaFileObject.Kind.class),
115                                                           false);
116
117                for (JavaFileObject jfo : content) {
118                    String name = jfo.getName();
119                    int lastSlash = name.lastIndexOf('/');
120                    name = lastSlash >= 0 ? name.substring(lastSlash + 1) : name;
121                    Path target = targetPath.resolve(pack.replace(".", sep) + sep + name);
122                    Files.createDirectories(target.getParent());
123                    try (InputStream in = jfo.openInputStream()) {
124                        Files.copy(in, target);
125                    }
126                }
127            }
128        }
129
130        System.setProperty("java.home", javaHome.toString());
131
132        try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
133            DiagnosticListener<JavaFileObject> noErrors = d -> {
134                if (d.getKind() == Diagnostic.Kind.ERROR)
135                    throw new IllegalStateException("Unexpected error: " + d);
136            };
137            ToolBox.JavaSource inputFile =
138                    new ToolBox.JavaSource("import java.util.List; class Test { List l; }");
139            List<JavaFileObject> inputFiles = Arrays.asList(inputFile);
140            boolean result =
141                    javaCompiler.getTask(null, fm, noErrors, null, null, inputFiles).call();
142            if (!result) {
143                throw new IllegalStateException("Could not compile correctly!");
144            }
145            JavacTask task =
146                    (JavacTask) javaCompiler.getTask(null, fm, noErrors, null, null, inputFiles);
147            task.parse();
148            TypeElement juList = task.getElements().getTypeElement("java.util.List");
149            if (juList == null)
150                throw new IllegalStateException("Cannot resolve java.util.List!");
151            URI listSource = ((ClassSymbol) juList).classfile.toUri();
152            if (!listSource.toString().startsWith(javaHome.toUri().toString()))
153                throw new IllegalStateException(  "Did not load java.util.List from correct place, " +
154                                                  "actual location: " + listSource.toString() +
155                                                "; expected prefix: " + javaHome.toUri());
156        }
157
158        System.err.println("finished.");
159    }
160    //where:
161        static final String[] REQUIRED_PACKAGES = {"java.lang", "java.io", "java.util"};
162
163    Path prepareJavaHome() throws IOException {
164        Path javaHome = new File("javahome").getAbsoluteFile().toPath();
165        delete(javaHome);
166        Files.createDirectory(javaHome);
167        return javaHome;
168    }
169
170    String sep = FileSystems.getDefault().getSeparator();
171    JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
172    String originalJavaHome = System.getProperty("java.home");
173
174    void delete(Path p) throws IOException {
175        if (!Files.exists(p))
176            return ;
177        if (Files.isDirectory(p)) {
178            try (DirectoryStream<Path> dir = Files.newDirectoryStream(p)) {
179                for (Path child : dir) {
180                    delete(child);
181                }
182            }
183        }
184        Files.delete(p);
185    }
186}
187