1 /*
   2  * Copyright (c) 2017, 2018, 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  * @library /test/lib
  27  * @build ExecJarWithAgent Main Agent AgentHelper
  28  *        jdk.test.lib.util.JarUtils
  29  * @run testng ExecJarWithAgent
  30  * @summary Test starting agents in executable JAR files
  31  */
  32 
  33 import java.nio.file.Path;
  34 import java.nio.file.Paths;
  35 import java.util.jar.Attributes;
  36 import java.util.jar.Manifest;
  37 import java.util.stream.Stream;
  38 
  39 import org.testng.annotations.Test;
  40 import static org.testng.Assert.*;
  41 
  42 import jdk.test.lib.process.ProcessTools;
  43 import jdk.test.lib.process.OutputAnalyzer;
  44 import jdk.test.lib.util.JarUtils;
  45 
  46 @Test
  47 public class ExecJarWithAgent {
  48 
  49     /**
  50      * Basic test of java -jar with agent in the executable JAR
  51      */
  52     public void testBasic() throws Exception {
  53         Manifest man = new Manifest();
  54         Attributes attrs = man.getMainAttributes();
  55         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
  56         attrs.put(Attributes.Name.MAIN_CLASS, "Main");
  57         attrs.put(new Attributes.Name("Launcher-Agent-Class"), "Agent");
  58 
  59         // require all capabilities
  60         attrs.put(new Attributes.Name("Can-Redefine-Classes"), "true");
  61         attrs.put(new Attributes.Name("Can-Retransform-Classes"), "true");
  62         attrs.put(new Attributes.Name("Can-Set-Native-Method-Prefix"), "true");
  63         attrs.put(new Attributes.Name("Boot-Class-Path"), "helper.jar");
  64 
  65         Path app = Paths.get("app.jar");
  66         Path dir = Paths.get(System.getProperty("test.classes"));
  67 
  68         Path[] paths = Stream.of("Main.class", "Agent.class")
  69                 .map(Paths::get)
  70                 .toArray(Path[]::new);
  71 
  72         JarUtils.createJarFile(app, man, dir, paths);
  73 
  74         // helper API to test that the BCP has been extended
  75         Path helper = Paths.get("helper.jar");
  76         JarUtils.createJarFile(helper, dir, "AgentHelper.class");
  77 
  78         // java -jar app.jar
  79         assertEquals(exec(app).getExitValue(), 0);
  80     }
  81 
  82     /**
  83      * Test that java -jar fails when the executable JAR has the
  84      * Launcher-Agent-Class attribute but the class cannot be loaded.
  85      */
  86     public void testBadAgentClass() throws Exception {
  87         Manifest man = new Manifest();
  88         Attributes attrs = man.getMainAttributes();
  89         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
  90         attrs.put(Attributes.Name.MAIN_CLASS, "Main");
  91 
  92         // agent class does not exist
  93         attrs.put(new Attributes.Name("Launcher-Agent-Class"), "BadAgent");
  94 
  95         Path app = Paths.get("app.jar");
  96         Path dir = Paths.get(System.getProperty("test.classes"));
  97 
  98         JarUtils.createJarFile(app, man, dir, Paths.get("Main.class"));
  99 
 100         // java -jar app.jar
 101         int exitCode = exec(app).shouldContain("ClassNotFoundException").getExitValue();
 102         assertNotEquals(exitCode, 0);
 103     }
 104 
 105     /**
 106      * Test that java -jar fails when the executable JAR has the
 107      * Launcher-Agent-Class attribute and the class does not define an
 108      * agentmain method.
 109      */
 110     public void testNoAgentMain() throws Exception {
 111         // manifest for the executable JAR
 112         Manifest man = new Manifest();
 113         Attributes attrs = man.getMainAttributes();
 114         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 115         attrs.put(Attributes.Name.MAIN_CLASS, "Main");
 116 
 117         // the main class does not define the agentmain method
 118         attrs.put(new Attributes.Name("Launcher-Agent-Class"), "Main");
 119 
 120         Path app = Paths.get("app.jar");
 121         Path dir = Paths.get(System.getProperty("test.classes"));
 122 
 123         JarUtils.createJarFile(app, man, dir, Paths.get("Main.class"));
 124 
 125         // java -jar app.jar
 126         int exitCode = exec(app).shouldContain("NoSuchMethodException").getExitValue();
 127         assertNotEquals(exitCode, 0);
 128     }
 129 
 130     /**
 131      * java -jar app.jar, returning the OutputAnalyzer to analyze the output
 132      */
 133     private OutputAnalyzer exec(Path appJar) throws Exception {
 134         return ProcessTools.executeTestJava("-jar", appJar.toString())
 135                 .outputTo(System.out)
 136                 .errorTo(System.out);
 137     }
 138 
 139 
 140 }