/* * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ /** * * * @author Adrian Colley * @author Laird Dornin * @author Peter Jones * @author Ann Wollrath * * The rmi library directory contains a set of simple utiltity classes * for use in rmi regression tests. * * NOTE: The JavaTest group has recommended that regression tests do * not make use of packages. */ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.net.URL; import java.net.MalformedURLException; import java.rmi.activation.Activatable; import java.rmi.activation.ActivationID; import java.rmi.NoSuchObjectException; import java.rmi.registry.Registry; import java.rmi.Remote; import java.rmi.server.UnicastRemoteObject; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.io.ByteArrayOutputStream; import java.security.AccessController; import java.security.PrivilegedAction; /** * Class of utility/library methods (i.e. procedures) that assist with * the writing and maintainance of rmi regression tests. */ public class TestLibrary { /** standard test port number for registry */ public final static int REGISTRY_PORT = 2006; /** port for rmid necessary: not used to actually start rmid */ public final static int RMID_PORT = 1098; static void mesg(Object mesg) { System.err.println("TEST_LIBRARY: " + mesg.toString()); } /** * Routines that enable rmi tests to fail in a uniformly * informative fashion. */ public static void bomb(String message, Exception e) { String testFailed = "TEST FAILED: "; if ((message == null) && (e == null)) { testFailed += " No relevant information"; } else if (e == null) { testFailed += message; } System.err.println(testFailed); if (e != null) { System.err.println("Test failed with: " + e.getMessage()); e.printStackTrace(System.err); } throw new TestFailedException(testFailed, e); } public static void bomb(String message) { bomb(message, null); } public static void bomb(Exception e) { bomb(null, e); } /** * Property accessors */ private static boolean getBoolean(String name) { return (new Boolean(getProperty(name, "false")).booleanValue()); } private static Integer getInteger(String name) { int val = 0; Integer value = null; String propVal = getProperty(name, null); if (propVal == null) { return null; } try { value = new Integer(Integer.parseInt(propVal)); } catch (NumberFormatException nfe) { } return value; } public static String getProperty(String property, String defaultVal) { final String prop = property; final String def = defaultVal; return ((String) java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public Object run() { return System.getProperty(prop, def); } })); } /** * Property mutators */ public static void setBoolean(String property, boolean value) { setProperty(property, (new Boolean(value)).toString()); } public static void setInteger(String property, int value) { setProperty(property, Integer.toString(value)); } public static void setProperty(String property, String value) { final String prop = property; final String val = value; java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public Object run() { System.setProperty(prop, val); return null; } }); } /** * Routines to print out a test's properties environment. */ public static void printEnvironment() { printEnvironment(System.err); } public static void printEnvironment(PrintStream out) { out.println("-------------------Test environment----------" + "---------"); for(Enumeration keys = System.getProperties().keys(); keys.hasMoreElements();) { String property = (String) keys.nextElement(); out.println(property + " = " + getProperty(property, null)); } out.println("---------------------------------------------" + "---------"); } /** * Routine that "works-around" a limitation in jtreg. * Currently it is not possible for a test to specify that the * test harness should build a given source file and install the * resulting class in a location that is not accessible from the * test's classpath. This method enables a test to move a * compiled test class file from the test's class directory into a * given "codebase" directory. As a result the test can only * access the class file for <code>className</code>if the test loads * it from a classloader (e.g. RMIClassLoader). * * Tests that use this routine must have the following permissions * granted to them: * * getProperty user.dir * getProperty etc. */ public static URL installClassInCodebase(String className, String codebase) throws MalformedURLException { return installClassInCodebase(className, codebase, true); } public static URL installClassInCodebase(String className, String codebase, boolean delete) throws MalformedURLException { /* * NOTES/LIMITATIONS: The class must not be in a named package, * and the codebase must be a relative path (it's created relative * to the working directory). */ String classFileName = className + ".class"; /* * Specify the file to contain the class definition. Make sure * that the codebase directory exists (underneath the working * directory). */ File dstDir = (new File(getProperty("user.dir", "."), codebase)); if (!dstDir.exists()) { if (!dstDir.mkdir()) { throw new RuntimeException( "could not create codebase directory"); } } File dstFile = new File(dstDir, classFileName); /* * Obtain the URL for the codebase. */ URL codebaseURL = dstDir.toURL(); /* * Specify where we will copy the class definition from, if * necessary. After the test is built, the class file can be * found in the "test.classes" directory. */ File srcDir = new File(getProperty("test.classes", ".")); File srcFile = new File(srcDir, classFileName); mesg(srcFile); mesg(dstFile); /* * If the class definition is not already located at the codebase, * copy it there from the test build area. */ if (!dstFile.exists()) { if (!srcFile.exists()) { throw new RuntimeException( "could not find class file to install in codebase " + "(try rebuilding the test): " + srcFile); } try { copyFile(srcFile, dstFile); } catch (IOException e) { throw new RuntimeException( "could not install class file in codebase"); } mesg("Installed class \"" + className + "\" in codebase " + codebaseURL); } /* * After the class definition is successfully installed at the * codebase, delete it from the test's CLASSPATH, so that it will * not be found there first before the codebase is searched. */ if (srcFile.exists()) { if (delete && !srcFile.delete()) { throw new RuntimeException( "could not delete duplicate class file in CLASSPATH"); } } return codebaseURL; } public static void copyFile(File srcFile, File dstFile) throws IOException { FileInputStream src = new FileInputStream(srcFile); FileOutputStream dst = new FileOutputStream(dstFile); byte[] buf = new byte[32768]; while (true) { int count = src.read(buf); if (count < 0) { break; } dst.write(buf, 0, count); } dst.close(); src.close(); } /** routine to unexport an object */ public static void unexport(Remote obj) { if (obj != null) { try { mesg("unexporting object..."); UnicastRemoteObject.unexportObject(obj, true); } catch (NoSuchObjectException munch) { } catch (Exception e) { e.getMessage(); e.printStackTrace(); } } } /** * Allow test framework to control the security manager set in * each test. * * @param managerClassName The class name of the security manager * to be instantiated and set if no security * manager has already been set. */ public static void suggestSecurityManager(String managerClassName) { SecurityManager manager = null; if (System.getSecurityManager() == null) { try { if (managerClassName == null) { managerClassName = TestParams.defaultSecurityManager; } manager = ((SecurityManager) Class. forName(managerClassName).newInstance()); } catch (ClassNotFoundException cnfe) { bomb("Security manager could not be found: " + managerClassName, cnfe); } catch (Exception e) { bomb("Error creating security manager. ", e); } System.setSecurityManager(manager); } } /** * Method to capture the stack trace of an exception and return it * as a string. */ public String stackTraceToString(Exception e) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(bos); e.printStackTrace(ps); return bos.toString(); } /** extra properties */ private static Properties props; /** * Returns extra test properties. Looks for the file "../../test.props" * and reads it in as a Properties file. Assuming the working directory * is "<path>/JTwork/scratch", this will find "<path>/test.props". */ private static synchronized Properties getExtraProperties() { if (props != null) { return props; } props = new Properties(); File f = new File(".." + File.separator + ".." + File.separator + "test.props"); if (!f.exists()) { return props; } try { FileInputStream in = new FileInputStream(f); try { props.load(in); } finally { in.close(); } } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("extra property setup failed", e); } return props; } /** * Returns an extra test property. Looks for the file "../../test.props" * and reads it in as a Properties file. Assuming the working directory * is "<path>/JTwork/scratch", this will find "<path>/test.props". * If the property isn't found, defaultVal is returned. */ public static String getExtraProperty(String property, String defaultVal) { return getExtraProperties().getProperty(property, defaultVal); } }