Path: blob/master/test/jdk/sun/misc/JarIndex/metaInfFilenames/Basic.java
41153 views
/*1* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 688771026* @summary Verify the impact of sun.misc.JarIndex.metaInfFilenames on ServiceLoader27* @modules jdk.jartool/sun.tools.jar28* jdk.httpserver29* jdk.compiler30* jdk.zipfs31* @run main/othervm Basic32*/3334import java.io.IOException;35import java.io.BufferedReader;36import java.io.File;37import java.io.FileInputStream;38import java.io.InputStream;39import java.io.InputStreamReader;40import java.io.OutputStream;41import java.net.InetSocketAddress;42import java.net.URI;43import java.net.URL;44import java.net.URLClassLoader;45import java.util.Arrays;46import java.util.Iterator;47import java.util.ServiceLoader;48import com.sun.net.httpserver.Headers;49import com.sun.net.httpserver.HttpExchange;50import com.sun.net.httpserver.HttpHandler;51import com.sun.net.httpserver.HttpServer;5253/**54* Verifies the impact of sun.misc.JarIndex.metaInfFilenames on ServiceLoader55* and on finding resources via Class.getResource.56*57* 1) Compile the test sources:58* jarA:59* META-INF/services/my.happy.land60* com/message/spi/MessageService.java61* a/A.java62* jarB:63* META-INF/JAVA2.DS64* META-INF/services/no.name.service65* b/B.java66* jarC:67* META-INF/fonts.mf68* META-INF/fonts/Company-corporate.ttf69* META-INF/fonts/kidpr.ttf70* META-INF/services/com.message.spi.MessageService71* my/impl/StandardMessageService.java72*73* 2) Build three jar files a.jar, b.jar, c.jar74*75* 3) Create an index in a.jar (jar -i a.jar b.jar c.jar)76* with sun.misc.JarIndex.metaInfFilenames=true77*78* 4) Start a HTTP server serving out the three jars.79*80* The test then tries to locate services/resources within the jars using81* URLClassLoader. Each request to the HTTP server is recorded to ensure82* only the correct amount of requests are being made.83*84*/8586public class Basic {87static final String slash = File.separator;88static final String[] testSources = {89"jarA" + slash + "a" + slash + "A.java",90"jarA" + slash + "com" + slash + "message" + slash + "spi" + slash + "MessageService.java",91"jarB" + slash + "b" + slash + "B.java",92"jarC" + slash + "my" + slash + "impl" + slash + "StandardMessageService.java"};9394static final String testSrc = System.getProperty("test.src");95static final String testSrcDir = testSrc != null ? testSrc : ".";96static final String testClasses = System.getProperty("test.classes");97static final String testClassesDir = testClasses != null ? testClasses : ".";9899static JarHttpServer httpServer;100101public static void main(String[] args) throws Exception {102103// Set global url cache to false so that we can track every jar request.104(new URL("http://localhost/")).openConnection().setDefaultUseCaches(false);105106buildTest();107108try {109httpServer = new JarHttpServer(testClassesDir);110httpServer.start();111112doTest(httpServer.getAddress());113114} catch (IOException ioe) {115ioe.printStackTrace();116} finally {117if (httpServer != null) { httpServer.stop(2); }118}119}120121static void buildTest() {122/* compile the source that will be used to generate the jars */123for (int i=0; i<testSources.length; i++)124testSources[i] = testSrcDir + slash + testSources[i];125126compile("-d" , testClassesDir,127"-sourcepath", testSrcDir,128testSources[0], testSources[1], testSources[2], testSources[3]);129130/* build the 3 jar files */131jar("-cf", testClassesDir + slash + "a.jar",132"-C", testClassesDir, "a",133"-C", testClassesDir, "com",134"-C", testSrcDir + slash + "jarA", "META-INF");135jar("-cf", testClassesDir + slash + "b.jar",136"-C", testClassesDir, "b",137"-C", testSrcDir + slash + "jarB", "META-INF");138jar("-cf", testClassesDir + slash + "c.jar",139"-C", testClassesDir, "my",140"-C", testSrcDir + slash + "jarC", "META-INF");141142/* Create an index in a.jar for b.jar and c.jar */143createIndex(testClassesDir);144}145146/* run jar <args> */147static void jar(String... args) {148debug("Running: jar " + Arrays.toString(args));149sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar");150if (!jar.run(args)) {151throw new RuntimeException("jar failed: args=" + Arrays.toString(args));152}153}154155/* run javac <args> */156static void compile(String... args) {157debug("Running: javac " + Arrays.toString(args));158if (com.sun.tools.javac.Main.compile(args) != 0) {159throw new RuntimeException("javac failed: args=" + Arrays.toString(args));160}161}162163static String jar;164static {165jar = System.getProperty("java.home") + slash+ "bin" + slash + "jar";166}167168/* create the index */169static void createIndex(String workingDir) {170// ProcessBuilder is used so that the current directory can be set171// to the directory that directly contains the jars.172debug("Running jar to create the index");173ProcessBuilder pb = new ProcessBuilder(174jar, "-J-Dsun.misc.JarIndex.metaInfFilenames=true", "-i", "a.jar", "b.jar", "c.jar");175pb.directory(new File(workingDir));176//pd.inheritIO();177try {178Process p = pb.start();179if(p.waitFor() != 0)180throw new RuntimeException("jar indexing failed");181182if(debug && p != null) {183String line = null;184BufferedReader reader =185new BufferedReader(new InputStreamReader(p.getInputStream()));186while((line = reader.readLine()) != null)187debug(line);188reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));189while((line = reader.readLine()) != null)190debug(line);191}192} catch(InterruptedException ie) { throw new RuntimeException(ie);193} catch(IOException e) { throw new RuntimeException(e); }194}195196static final boolean debug = true;197198static void debug(Object message) { if (debug) System.out.println(message); }199200/* service define in c.jar */201static final String messageService = "com.message.spi.MessageService";202203/* a service that is not defined in any of the jars */204static final String unknownService = "java.lang.Object";205206static void doTest(InetSocketAddress serverAddress) throws IOException {207URL baseURL = new URL("http://localhost:" + serverAddress.getPort() + "/");208209int failed = 0;210211// Tests using java.util.SerivceLoader212if (!javaUtilServiceLoaderTest(baseURL, messageService, true, false, true)) {213System.out.println("Test: ServiceLoader looking for " + messageService + ", failed");214failed++;215}216if (!javaUtilServiceLoaderTest(baseURL, unknownService, false, false, false)) {217System.out.println("Test: ServiceLoader looking for " + unknownService + " failed");218failed++;219}220221// Tests using java.lang.Class (similar to the FontManager in javafx)222if (!klassLoader(baseURL, "/META-INF/fonts.mf", true, false, true)) {223System.out.println("Test: klassLoader looking for /META-INF/fonts.mf failed");224failed++;225}226if (!klassLoader(baseURL, "/META-INF/unknown.mf", false, false, false)) {227System.out.println("Test: klassLoader looking for /META-INF/unknown.mf failed");228failed++;229}230231if (failed > 0)232throw new RuntimeException("Failed: " + failed + " tests");233}234235static boolean javaUtilServiceLoaderTest(URL baseURL,236String serviceClass,237boolean expectToFind,238boolean expectbDotJar,239boolean expectcDotJar) throws IOException {240debug("----------------------------------");241debug("Running test with java.util.ServiceLoader looking for " + serviceClass);242URLClassLoader loader = getLoader(baseURL);243httpServer.reset();244245Class<?> messageServiceClass = null;246try {247messageServiceClass = loader.loadClass(serviceClass);248} catch (ClassNotFoundException cnfe) {249System.err.println(cnfe);250throw new RuntimeException("Error in test: " + cnfe);251}252253Iterator<?> iterator = (ServiceLoader.load(messageServiceClass, loader)).iterator();254if (expectToFind && !iterator.hasNext()) {255debug(messageServiceClass + " NOT found.");256return false;257}258259while (iterator.hasNext()) {260debug("found " + iterator.next() + " " + messageService);261}262263debug("HttpServer: " + httpServer);264265if (!expectbDotJar && httpServer.bDotJar > 0) {266debug("Unexpeced request sent to the httpserver for b.jar");267return false;268}269if (!expectcDotJar && httpServer.cDotJar > 0) {270debug("Unexpeced request sent to the httpserver for c.jar");271return false;272}273274return true;275}276277/* Tries to find a resource in a similar way to the font manager in javafx278* com.sun.javafx.scene.text.FontManager */279static boolean klassLoader(URL baseURL,280String resource,281boolean expectToFind,282boolean expectbDotJar,283boolean expectcDotJar) throws IOException {284debug("----------------------------------");285debug("Running test looking for " + resource);286URLClassLoader loader = getLoader(baseURL);287httpServer.reset();288289Class<?> ADotAKlass = null;290try {291ADotAKlass = loader.loadClass("a.A");292} catch (ClassNotFoundException cnfe) {293System.err.println(cnfe);294throw new RuntimeException("Error in test: " + cnfe);295}296297URL u = ADotAKlass.getResource(resource);298if (expectToFind && u == null) {299System.out.println("Expected to find " + resource + " but didn't");300return false;301}302303debug("HttpServer: " + httpServer);304305if (!expectbDotJar && httpServer.bDotJar > 0) {306debug("Unexpeced request sent to the httpserver for b.jar");307return false;308}309if (!expectcDotJar && httpServer.cDotJar > 0) {310debug("Unexpeced request sent to the httpserver for c.jar");311return false;312}313314return true;315}316317static URLClassLoader getLoader(URL baseURL) throws IOException {318ClassLoader loader = Basic.class.getClassLoader();319320while (loader.getParent() != null)321loader = loader.getParent();322323return new URLClassLoader( new URL[]{324new URL(baseURL, "a.jar"),325new URL(baseURL, "b.jar"),326new URL(baseURL, "c.jar")}, loader );327}328329/**330* HTTP Server to server the jar files.331*/332static class JarHttpServer implements HttpHandler {333final String docsDir;334final HttpServer httpServer;335int aDotJar, bDotJar, cDotJar;336337JarHttpServer(String docsDir) throws IOException {338this.docsDir = docsDir;339340httpServer = HttpServer.create(new InetSocketAddress(0), 0);341httpServer.createContext("/", this);342}343344void start() throws IOException {345httpServer.start();346}347348void stop(int delay) {349httpServer.stop(delay);350}351352InetSocketAddress getAddress() {353return httpServer.getAddress();354}355356void reset() {357aDotJar = bDotJar = cDotJar = 0;358}359360@Override361public String toString() {362return "aDotJar=" + aDotJar + ", bDotJar=" + bDotJar + ", cDotJar=" + cDotJar;363}364365public void handle(HttpExchange t) throws IOException {366InputStream is = t.getRequestBody();367Headers map = t.getRequestHeaders();368Headers rmap = t.getResponseHeaders();369URI uri = t.getRequestURI();370371debug("Server: received request for " + uri);372String path = uri.getPath();373if (path.endsWith("a.jar"))374aDotJar++;375else if (path.endsWith("b.jar"))376bDotJar++;377else if (path.endsWith("c.jar"))378cDotJar++;379else380System.out.println("Unexpected resource request" + path);381382while (is.read() != -1);383is.close();384385File file = new File(docsDir, path);386if (!file.exists())387throw new RuntimeException("Error: request for " + file);388long clen = file.length();389t.sendResponseHeaders (200, clen);390OutputStream os = t.getResponseBody();391FileInputStream fis = new FileInputStream(file);392try {393byte[] buf = new byte [16 * 1024];394int len;395while ((len=fis.read(buf)) != -1) {396os.write (buf, 0, len);397}398} catch (IOException e) {399e.printStackTrace();400}401fis.close();402os.close();403}404}405}406407408