1 /*
   2  * Copyright (c) 1999, 2012, 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 /* @test
  25  * @bug 4242317
  26  * @summary When a class that can be found in the CLASSPATH of the rmiregistry
  27  * tool is marshalled via RMI, it should be annotated with the value of the
  28  * java.rmi.server.codebase property, not the list of "file:" URLs for the
  29  * actual elements of the CLASSPATH.
  30  * @author Peter Jones
  31  *
  32  * @library ../../testlibrary
  33  * @build ClassPathCodebase Dummy TestLibrary
  34  * @run main/othervm/policy=security.policy ClassPathCodebase
  35  */
  36 
  37 import java.io.*;
  38 import java.net.*;
  39 import java.rmi.*;
  40 import java.rmi.server.*;
  41 import java.rmi.registry.*;
  42 import java.util.Arrays;
  43 
  44 public class ClassPathCodebase {
  45 
  46     /** wait 10 seconds for the registry process to be ready to call */
  47     private final static long REGISTRY_WAIT = 15000;
  48 
  49     private final static String dummyClassName = "Dummy";
  50 
  51     private final static String dummyBinding = "DummyObject";
  52 
  53     private final static String importCodebase = "codebase_IMPORT_";
  54     private final static String exportCodebase = "codebase_EXPORT_";
  55 
  56     public static void main(String[] args) {
  57 
  58         System.err.println("\nRegression test for bug 4242317\n");
  59 
  60         TestLibrary.suggestSecurityManager("java.lang.SecurityManager");
  61 
  62         Process rmiregistry = null;
  63 
  64         try {
  65             /*
  66              * Install a dummy class in two codebases: one that will be in
  67              * the rmiregistry's CLASSPATH (the "import" codebase) and one
  68              * that will be in the rmiregistry's "java.rmi.server.codebase"
  69              * property (the "export" codebase).
  70              */
  71             URL importCodebaseURL = TestLibrary.installClassInCodebase(
  72                 dummyClassName, importCodebase, false);
  73             URL exportCodebaseURL = TestLibrary.installClassInCodebase(
  74                 dummyClassName, exportCodebase, true);
  75 
  76             /*
  77              * Spawn an rmiregistry in the "import" codebase directory.
  78              */
  79             File rmiregistryDir =
  80                 new File(System.getProperty("user.dir", "."), importCodebase);
  81 
  82             String rmiregistryCommand =
  83                 System.getProperty("java.home") + File.separator +
  84                 "bin" + File.separator + "rmiregistry";
  85 
  86             int port = TestLibrary.getUnusedRandomPort();
  87             String cmdarray[] = new String[] {
  88                 rmiregistryCommand,
  89                 "-J-Denv.class.path=.",
  90                 "-J-Djava.rmi.server.codebase=" + exportCodebaseURL,
  91                 Integer.toString(port) };
  92 
  93             System.err.println("\nCommand used to spawn rmiregistry process:");
  94             System.err.println("\t" + Arrays.asList(cmdarray).toString());
  95 
  96             rmiregistry = Runtime.getRuntime().exec(cmdarray, null, rmiregistryDir);
  97 
  98             // pipe rmiregistry output to our output, for debugging failures
  99             StreamPipe.plugTogether(rmiregistry.getInputStream(), System.err);
 100             StreamPipe.plugTogether(rmiregistry.getErrorStream(), System.err);
 101 
 102             /*
 103              * Wait for the registry to initialize and be ready to call.
 104              */
 105             Thread.sleep(REGISTRY_WAIT);
 106             System.err.println();
 107 
 108             /*
 109              * Create an instance of the dummy class, finding it from the
 110              * "import" codebase.
 111              */
 112             ClassLoader loader = URLClassLoader.newInstance(
 113                 new URL[] { importCodebaseURL });
 114             Class dummyClass = Class.forName(dummyClassName, false, loader);
 115             Remote dummyObject = (Remote) dummyClass.newInstance();
 116 
 117             /*
 118              * Find the registry that we created and bind the
 119              * dummy object to it.
 120              */
 121             Registry registry = LocateRegistry.getRegistry(
 122                 "localhost", port);
 123 
 124             try {
 125                 registry.bind(dummyBinding, dummyObject);
 126                 System.err.println("Bound dummy object in registry");
 127             } catch (java.rmi.ConnectException e) {
 128                 System.err.println("Error: rmiregistry not started in time");
 129                 throw e;
 130             } catch (ServerException e) {
 131                 if (e.detail instanceof UnmarshalException &&
 132                     ((UnmarshalException) e.detail).detail instanceof
 133                         ClassNotFoundException)
 134                 {
 135                     System.err.println(
 136                         "Error: another registry running on port " +
 137                         port + "?");
 138                 }
 139                 throw e;
 140             }
 141 
 142             /*
 143              * Look up the dummy object from our registry and make sure
 144              * that its class was annotated with the "export" codebase.
 145              */
 146             Remote dummyLookup = registry.lookup(dummyBinding);
 147             System.err.println(
 148                 "Looked up dummy object from registry: " + dummyLookup);
 149             Class dummyLookupClass = dummyLookup.getClass();
 150             String dummyLookupAnnotation =
 151                 RMIClassLoader.getClassAnnotation(dummyLookupClass);
 152             System.err.println(
 153                 "Class annotation from registry: " + dummyLookupAnnotation);
 154 
 155             System.err.println();
 156             if (dummyLookupAnnotation.indexOf(exportCodebase) >= 0) {
 157                 System.err.println("TEST PASSED");
 158             } else if (dummyLookupAnnotation.indexOf(importCodebase) >= 0) {
 159                 throw new RuntimeException(
 160                     "rmiregistry annotated with CLASSPATH element URL");
 161             } else {
 162                 throw new RuntimeException(
 163                     "rmiregistry used unexpected annotation: \"" +
 164                     dummyLookupAnnotation + "\"");
 165             }
 166 
 167         } catch (Exception e) {
 168             e.printStackTrace();
 169             throw new RuntimeException("TEST FAILED: " + e.toString());
 170         } finally {
 171             if (rmiregistry != null) {
 172                 rmiregistry.destroy();
 173             }
 174         }
 175     }
 176 }