test/testlibrary/ClassFileInstaller.java

Thu, 26 Jul 2018 06:16:09 -0400

author
vaibhav
date
Thu, 26 Jul 2018 06:16:09 -0400
changeset 9421
6cfec782c42c
parent 5100
43083e670adf
child 9448
73d689add964
permissions
-rw-r--r--

8189762: [TESTBUG] Create tests for JDK-8146115 container awareness and resource configuration
Summary: Created tests for the feature
Reviewed-by: mseledtsov

mgerdin@4637 1 /*
vaibhav@9421 2 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
mgerdin@4637 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mgerdin@4637 4 *
mgerdin@4637 5 * This code is free software; you can redistribute it and/or modify it
mgerdin@4637 6 * under the terms of the GNU General Public License version 2 only, as
mgerdin@4637 7 * published by the Free Software Foundation.
mgerdin@4637 8 *
mgerdin@4637 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mgerdin@4637 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mgerdin@4637 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mgerdin@4637 12 * version 2 for more details (a copy is included in the LICENSE file that
mgerdin@4637 13 * accompanied this code).
mgerdin@4637 14 *
mgerdin@4637 15 * You should have received a copy of the GNU General Public License version
mgerdin@4637 16 * 2 along with this work; if not, write to the Free Software Foundation,
mgerdin@4637 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mgerdin@4637 18 *
mgerdin@4637 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mgerdin@4637 20 * or visit www.oracle.com if you need additional information or have any
mgerdin@4637 21 * questions.
mgerdin@4637 22 */
mgerdin@4637 23
vaibhav@9421 24 import java.io.ByteArrayInputStream;
vaibhav@9421 25 import java.io.File;
vaibhav@9421 26 import java.io.FileInputStream;
vaibhav@9421 27 import java.io.FileOutputStream;
vaibhav@9421 28 import java.io.FileNotFoundException;
mgerdin@4637 29 import java.io.InputStream;
vaibhav@9421 30 import java.io.ByteArrayInputStream;
mgerdin@4637 31 import java.nio.file.Files;
mgerdin@4637 32 import java.nio.file.Path;
mgerdin@4637 33 import java.nio.file.Paths;
mgerdin@4637 34 import java.nio.file.StandardCopyOption;
vaibhav@9421 35 import java.util.zip.ZipEntry;
vaibhav@9421 36 import java.util.zip.ZipOutputStream;
mgerdin@4637 37
mgerdin@4637 38 /**
vaibhav@9421 39 * Dump a class file for a class on the class path in the current directory, or
vaibhav@9421 40 * in the specified JAR file. This class is usually used when you build a class
vaibhav@9421 41 * from a test library, but want to use this class in a sub-process.
vaibhav@9421 42 *
vaibhav@9421 43 * For example, to build the following library class:
vaibhav@9421 44 * test/lib/sun/hotspot/WhiteBox.java
vaibhav@9421 45 *
vaibhav@9421 46 * You would use the following tags:
vaibhav@9421 47 *
vaibhav@9421 48 * @library /test/lib
vaibhav@9421 49 * @build sun.hotspot.WhiteBox
vaibhav@9421 50 *
vaibhav@9421 51 * JTREG would build the class file under
vaibhav@9421 52 * ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class
vaibhav@9421 53 *
vaibhav@9421 54 * With you run your main test class using "@run main MyMainClass", JTREG would setup the
vaibhav@9421 55 * -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to
vaibhav@9421 56 * load the WhiteBox class.
vaibhav@9421 57 *
vaibhav@9421 58 * However, if you run a sub process, and do not wish to use the exact same -classpath,
vaibhav@9421 59 * You can use ClassFileInstaller to ensure that WhiteBox is available in the current
vaibhav@9421 60 * directory of your test:
vaibhav@9421 61 *
vaibhav@9421 62 * @run main ClassFileInstaller sun.hotspot.WhiteBox
vaibhav@9421 63 *
vaibhav@9421 64 * Or, you can use the -jar option to store the class in the specified JAR file. If a relative
vaibhav@9421 65 * path name is given, the JAR file would be relative to the current directory of
vaibhav@9421 66 *
vaibhav@9421 67 * @run main ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox
mgerdin@4637 68 */
mgerdin@4637 69 public class ClassFileInstaller {
mgerdin@4637 70 /**
vaibhav@9421 71 * You can enable debug tracing of ClassFileInstaller by running JTREG with
vaibhav@9421 72 * jtreg -DClassFileInstaller.debug=true ... <names of tests>
vaibhav@9421 73 */
vaibhav@9421 74 public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug");
vaibhav@9421 75
vaibhav@9421 76 /**
mgerdin@4637 77 * @param args The names of the classes to dump
mgerdin@4637 78 * @throws Exception
mgerdin@4637 79 */
mgerdin@4637 80 public static void main(String... args) throws Exception {
vaibhav@9421 81 if (args.length > 1 && args[0].equals("-jar")) {
vaibhav@9421 82 if (args.length < 2) {
vaibhav@9421 83 throw new RuntimeException("Usage: ClassFileInstaller <options> <classes>\n" +
vaibhav@9421 84 "where possible options include:\n" +
vaibhav@9421 85 " -jar <path> Write to the JAR file <path>");
vaibhav@9421 86 }
vaibhav@9421 87 writeJar(args[1], null, args, 2, args.length);
vaibhav@9421 88 } else {
vaibhav@9421 89 if (DEBUG) {
vaibhav@9421 90 System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir"));
vaibhav@9421 91 }
vaibhav@9421 92 for (String arg : args) {
vaibhav@9421 93 writeClassToDisk(arg);
vaibhav@9421 94 }
vaibhav@9421 95 }
vaibhav@9421 96 }
mgerdin@4637 97
vaibhav@9421 98 public static class Manifest {
vaibhav@9421 99 private InputStream in;
mgerdin@4637 100
vaibhav@9421 101 private Manifest(InputStream in) {
vaibhav@9421 102 this.in = in;
vaibhav@9421 103 }
vaibhav@9421 104
vaibhav@9421 105 static Manifest fromSourceFile(String fileName) throws Exception {
vaibhav@9421 106 String pathName = System.getProperty("test.src") + File.separator + fileName;
vaibhav@9421 107 return new Manifest(new FileInputStream(pathName));
vaibhav@9421 108 }
vaibhav@9421 109
vaibhav@9421 110 // Example:
vaibhav@9421 111 // String manifest = "Premain-Class: RedefineClassHelper\n" +
vaibhav@9421 112 // "Can-Redefine-Classes: true\n";
vaibhav@9421 113 // ClassFileInstaller.writeJar("redefineagent.jar",
vaibhav@9421 114 // ClassFileInstaller.Manifest.fromString(manifest),
vaibhav@9421 115 // "RedefineClassHelper");
vaibhav@9421 116 static Manifest fromString(String manifest) throws Exception {
vaibhav@9421 117 return new Manifest(new ByteArrayInputStream(manifest.getBytes()));
vaibhav@9421 118 }
vaibhav@9421 119
vaibhav@9421 120 public InputStream getInputStream() {
vaibhav@9421 121 return in;
vaibhav@9421 122 }
vaibhav@9421 123 }
vaibhav@9421 124
vaibhav@9421 125 private static void writeJar(String jarFile, Manifest manifest, String classes[], int from, int to) throws Exception {
vaibhav@9421 126 if (DEBUG) {
vaibhav@9421 127 System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile));
vaibhav@9421 128 }
vaibhav@9421 129
vaibhav@9421 130 (new File(jarFile)).delete();
vaibhav@9421 131 FileOutputStream fos = new FileOutputStream(jarFile);
vaibhav@9421 132 ZipOutputStream zos = new ZipOutputStream(fos);
vaibhav@9421 133
vaibhav@9421 134 // The manifest must be the first or second entry. See comments in JarInputStream
vaibhav@9421 135 // constructor and JDK-5046178.
vaibhav@9421 136 if (manifest != null) {
vaibhav@9421 137 writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream());
vaibhav@9421 138 }
vaibhav@9421 139
vaibhav@9421 140 for (int i=from; i<to; i++) {
vaibhav@9421 141 writeClassToDisk(zos, classes[i]);
vaibhav@9421 142 }
vaibhav@9421 143
vaibhav@9421 144 zos.close();
vaibhav@9421 145 fos.close();
vaibhav@9421 146 }
vaibhav@9421 147
vaibhav@9421 148 /*
vaibhav@9421 149 * You can call ClassFileInstaller.writeJar() from your main test class instead of
vaibhav@9421 150 * using "@run ClassFileInstaller -jar ...". E.g.,
vaibhav@9421 151 *
vaibhav@9421 152 * String jarPath = ClassFileInstaller.getJarPath("myjar.jar", "sun.hotspot.WhiteBox")
vaibhav@9421 153 *
vaibhav@9421 154 * If you call this API, make sure you build ClassFileInstaller with the following tags:
vaibhav@9421 155 *
vaibhav@9421 156 * @library testlibrary
vaibhav@9421 157 * @build ClassFileInstaller
vaibhav@9421 158 */
vaibhav@9421 159 public static String writeJar(String jarFile, String... classes) throws Exception {
vaibhav@9421 160 writeJar(jarFile, null, classes, 0, classes.length);
vaibhav@9421 161 return getJarPath(jarFile);
vaibhav@9421 162 }
vaibhav@9421 163
vaibhav@9421 164 public static String writeJar(String jarFile, Manifest manifest, String... classes) throws Exception {
vaibhav@9421 165 writeJar(jarFile, manifest, classes, 0, classes.length);
vaibhav@9421 166 return getJarPath(jarFile);
vaibhav@9421 167 }
vaibhav@9421 168
vaibhav@9421 169 /**
vaibhav@9421 170 * This returns the absolute path to the file specified in "@ClassFileInstaller -jar myjar.jar",
vaibhav@9421 171 * In your test program, instead of using the JAR file name directly:
vaibhav@9421 172 *
vaibhav@9421 173 * String jarPath = "myjar.jar";
vaibhav@9421 174 *
vaibhav@9421 175 * you should call this function, like:
vaibhav@9421 176 *
vaibhav@9421 177 * String jarPath = ClassFileInstaller.getJarPath("myjar.jar")
vaibhav@9421 178 *
vaibhav@9421 179 * The reasons are:
vaibhav@9421 180 * (1) Using absolute path makes it easy to cut-and-paste from the JTR file and rerun your
vaibhav@9421 181 * test in any directory.
vaibhav@9421 182 * (2) In the future, we may make the JAR file name unique to avoid clobbering
vaibhav@9421 183 * during parallel JTREG execution.
vaibhav@9421 184 *
vaibhav@9421 185 */
vaibhav@9421 186 public static String getJarPath(String jarFileName) {
vaibhav@9421 187 return new File(jarFileName).getAbsolutePath();
vaibhav@9421 188 }
vaibhav@9421 189
vaibhav@9421 190 public static void writeClassToDisk(String className) throws Exception {
vaibhav@9421 191 writeClassToDisk((ZipOutputStream)null, className);
vaibhav@9421 192 }
vaibhav@9421 193 private static void writeClassToDisk(ZipOutputStream zos, String className) throws Exception {
vaibhav@9421 194 writeClassToDisk(zos, className, "");
vaibhav@9421 195 }
vaibhav@9421 196
vaibhav@9421 197 public static void writeClassToDisk(String className, String prependPath) throws Exception {
vaibhav@9421 198 writeClassToDisk(null, className, prependPath);
vaibhav@9421 199 }
vaibhav@9421 200 private static void writeClassToDisk(ZipOutputStream zos, String className, String prependPath) throws Exception {
vaibhav@9421 201 ClassLoader cl = ClassFileInstaller.class.getClassLoader();
vaibhav@9421 202
vaibhav@9421 203 // Convert dotted class name to a path to a class file
vaibhav@9421 204 String pathName = className.replace('.', '/').concat(".class");
vaibhav@9421 205 InputStream is = cl.getResourceAsStream(pathName);
vaibhav@9421 206 if (is == null) {
vaibhav@9421 207 throw new RuntimeException("Failed to find " + pathName);
vaibhav@9421 208 }
vaibhav@9421 209 if (prependPath.length() > 0) {
vaibhav@9421 210 pathName = prependPath + "/" + pathName;
vaibhav@9421 211 }
vaibhav@9421 212 writeToDisk(zos, pathName, is);
vaibhav@9421 213 }
vaibhav@9421 214
vaibhav@9421 215 public static void writeClassToDisk(String className, byte[] bytecode) throws Exception {
vaibhav@9421 216 writeClassToDisk(null, className, bytecode);
vaibhav@9421 217 }
vaibhav@9421 218 private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception {
vaibhav@9421 219 writeClassToDisk(zos, className, bytecode, "");
vaibhav@9421 220 }
vaibhav@9421 221
vaibhav@9421 222 public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception {
vaibhav@9421 223 writeClassToDisk(null, className, bytecode, prependPath);
vaibhav@9421 224 }
vaibhav@9421 225 private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception {
vaibhav@9421 226 // Convert dotted class name to a path to a class file
vaibhav@9421 227 String pathName = className.replace('.', '/').concat(".class");
vaibhav@9421 228 if (prependPath.length() > 0) {
vaibhav@9421 229 pathName = prependPath + "/" + pathName;
vaibhav@9421 230 }
vaibhav@9421 231 writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode));
vaibhav@9421 232 }
vaibhav@9421 233
vaibhav@9421 234 private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception {
vaibhav@9421 235 if (DEBUG) {
vaibhav@9421 236 System.out.println("ClassFileInstaller: Writing " + pathName);
vaibhav@9421 237 }
vaibhav@9421 238 if (zos != null) {
vaibhav@9421 239 ZipEntry ze = new ZipEntry(pathName);
vaibhav@9421 240 zos.putNextEntry(ze);
vaibhav@9421 241 byte[] buf = new byte[1024];
vaibhav@9421 242 int len;
vaibhav@9421 243 while ((len = is.read(buf))>0){
vaibhav@9421 244 zos.write(buf, 0, len);
vaibhav@9421 245 }
vaibhav@9421 246 } else {
mgerdin@4637 247 // Create the class file's package directory
mgerdin@4637 248 Path p = Paths.get(pathName);
coleenp@5100 249 if (pathName.contains("/")) {
coleenp@5100 250 Files.createDirectories(p.getParent());
coleenp@5100 251 }
mgerdin@4637 252 // Create the class file
mgerdin@4637 253 Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
mgerdin@4637 254 }
vaibhav@9421 255 is.close();
mgerdin@4637 256 }
mgerdin@4637 257 }

mercurial