You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2012/01/21 08:28:36 UTC
svn commit: r1234278 [13/29] - in /river/tck: ./ configs/ doc/ doc/api/
doc/api/com/ doc/api/com/sun/ doc/api/com/sun/jini/
doc/api/com/sun/jini/compat/ doc/api/com/sun/jini/compat/admin1/
doc/api/com/sun/jini/compat/admin2/ doc/api/com/sun/jini/compat...
Added: river/tck/src/com/sun/jini/compat/admin2/ServiceDestroyer.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/admin2/ServiceDestroyer.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/admin2/ServiceDestroyer.java (added)
+++ river/tck/src/com/sun/jini/compat/admin2/ServiceDestroyer.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.admin2;
+
+import net.jini.admin.Administrable;
+
+import com.sun.jini.admin.DestroyAdmin;
+import com.sun.jini.start.SharedActivatableServiceDescriptor;
+
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.UnknownObjectException;
+import java.rmi.activation.ActivationGroup;
+import java.rmi.RemoteException;
+
+/**
+ * This class provides static methods that can be used to destroy a service.
+ */
+public class ServiceDestroyer {
+
+ public static final int DESTROY_SUCCESS = 0;
+ /* Failure return codes */
+ public static final int SERVICE_NOT_ADMINISTRABLE = -1;
+ public static final int SERVICE_NOT_DESTROY_ADMIN = -2;
+ public static final int DEACTIVATION_TIMEOUT = -3;
+ public static final int PERSISTENT_STORE_EXISTS = -4;
+
+ /**
+ * Administratively destroys the service referenced by the input
+ * parameter. The service input to this method must implement
+ * both <code>net.jini.admin.Administrable</code> and the
+ * <code>com.sun.jini.admin.DestroyAdmin</code> interfaces
+ * in order for this method to successfully destroy the service.
+ *
+ * @param service reference to the service to destroy
+ *
+ * @return <code>int</code> value that indicates either success or
+ * one of a number of possible reasons for failure to destroy
+ * the service. Possible values are:
+ * <p><ul>
+ * <li> ServiceDestroyer.DESTROY_SUCCESS
+ * <li> ServiceDestroyer.SERVICE_NOT_ADMINISTRABLE - returned when
+ * the service to destroy is not an instance of
+ * net.jini.admin.Administrable
+ * <li> ServiceDestroyer.SERVICE_NOT_DESTROY_ADMIN - returned when
+ * the service to destroy is not an instance of
+ * com.sun.jini.admin.DestroyAdmin
+ * </ul>
+ *
+ * @throws java.rmi.RemoteException typically, this exception occurs when
+ * there is a communication failure between the client and the
+ * service's backend. When this exception does occur, the
+ * service may or may not have been successfully destroyed.
+ */
+ public static int destroy(Object service) throws RemoteException {
+ /* First, test that the service implements both of the appropriate
+ * administration interfaces
+ */
+ DestroyAdmin destroyAdmin = null;
+ if( !(service instanceof Administrable) ) {
+ return SERVICE_NOT_ADMINISTRABLE;
+ }
+ Object admin = ((Administrable)service).getAdmin();
+ if( !(admin instanceof DestroyAdmin) ) {
+ return SERVICE_NOT_DESTROY_ADMIN;
+ }
+ destroyAdmin = (DestroyAdmin)admin;
+ destroyAdmin.destroy();
+ return DESTROY_SUCCESS;
+ }
+
+ /**
+ * Administratively destroys the service referenced by the
+ * <code>proxy</code> parameter, which is assumed to be running
+ * under a shared VM environment. This method attempts to verify
+ * that the desired service is indeed destroyed by verifying that
+ * the service's activation information/descriptor is no longer
+ * registered with the activation system.
+ *
+ * @param created the id of the activation group in which the service to
+ * destroy is registered, the activation ID of the
+ * service to destroy, and the reference to the service
+ * to destroy
+ * @param nSecsWait the number of seconds to wait for the service's
+ * activation descriptor to be no longer registered with
+ * the activation system
+ *
+ * @return <code>int</code> value that indicates either success or
+ * one of a number of possible reasons for failure to destroy
+ * the service. Possible values are:
+ * <p><ul>
+ * <li> ServiceDestroyer.DESTROY_SUCCESS
+ * <li> ServiceDestroyer.SERVICE_NOT_ADMINISTRABLE - returned when
+ * the service to destroy is not an instance of
+ * net.jini.admin.Administrable
+ * <li> ServiceDestroyer.SERVICE_NOT_DESTROY_ADMIN - returned when
+ * the service to destroy is not an instance of
+ * com.sun.jini.admin.DestroyAdmin
+ * <li> ServiceDestroyer.DEACTIVATION_TIMEOUT - returned when the
+ * service's activation descriptor is still registered with the
+ * activation system after the number of seconds to wait have passed
+ * <li> ServiceDestroyer.PERSISTENT_STORE_EXISTS - returned when the
+ * directory in which the service stores its persistent state
+ * still exists after the service has been successfully destroyed
+ * </ul>
+ *
+ * @throws java.rmi.RemoteException typically, this exception occurs when
+ * there is a communication failure between the client and the
+ * service's backend. When this exception does occur, the
+ * service may or may not have been successfully destroyed.
+ * @throws java.rmi.activation.ActivationException typically, this
+ * exception occurs when problems arise while attempting to
+ * interact with the activation system
+ */
+ public static int destroy(
+ SharedActivatableServiceDescriptor.Created created, int nSecsWait)
+ throws RemoteException, ActivationException
+ {
+ Object proxy = created.proxy;
+ int destroyCode = destroy(proxy);
+ if(destroyCode != DESTROY_SUCCESS) return destroyCode;
+ /* Verify the service has actually been destroyed by waiting until
+ * service's activation ID is no longer registered with the
+ * activation system.
+ *
+ * Since an exception will be thrown when an attempt is made to
+ * retrieve an activation descriptor for an ID which is not
+ * registered, this method makes repeated attempts to retrieve the
+ * activation descriptor until such an exception is thrown,
+ * or until the indicated number of seconds to wait has passed.
+ */
+ boolean deactivated = false;
+ for(int i = 0; i < nSecsWait; i++) {
+ try {
+ ActivationGroup.getSystem().getActivationDesc(created.aid);
+ } catch (UnknownObjectException e) {
+ deactivated = true;
+ break;
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) { }
+ }
+ if(!deactivated) return DEACTIVATION_TIMEOUT;
+ return DESTROY_SUCCESS;
+ }
+
+}
+
Propchange: river/tck/src/com/sun/jini/compat/admin2/ServiceDestroyer.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/admin2/ServiceStarterAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/admin2/ServiceStarterAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/admin2/ServiceStarterAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/admin2/ServiceStarterAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,365 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.sun.jini.compat.admin2;
+
+import java.rmi.RemoteException;
+import java.rmi.activation.ActivationException;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.activation.ActivationGroupID;
+import java.io.IOException;
+import java.io.File;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import com.sun.jini.compat.harness.SysConfig;
+import com.sun.jini.compat.harness.Config;
+import com.sun.jini.compat.harness.BasicServiceAdmin;
+import com.sun.jini.compat.harness.BasicLookupAdmin;
+import com.sun.jini.compat.harness.TestUtility;
+
+import com.sun.jini.start.SharedGroup;
+import com.sun.jini.start.ServiceDescriptor;
+import com.sun.jini.start.NonActivatableServiceDescriptor;
+import com.sun.jini.start.SharedActivatableServiceDescriptor;
+import com.sun.jini.start.SharedActivationGroupDescriptor;
+import net.jini.core.lookup.ServiceRegistrar;
+import net.jini.core.lookup.ServiceItem;
+import net.jini.core.lookup.ServiceTemplate;
+import net.jini.core.lookup.ServiceID;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationProvider;
+import net.jini.config.ConfigurationException;
+
+/**
+ * This class implements the BasicServiceAdmin and BasicLookupAdmin
+ * interfaces to automate the testing of any <b>activatable</b> program that can be
+ * started by the ServiceStarter framework. See the <code>start</code> method
+ * documentation for config file properties supported by this Admin.
+ */
+public class ServiceStarterAdmin implements BasicServiceAdmin, BasicLookupAdmin
+{
+
+ protected Config compatConfig;
+ protected SysConfig compatSysConfig;
+ protected PrintWriter log;
+
+ protected NonActivatableServiceDescriptor.Created nonActivatableCreated;
+ protected SharedActivatableServiceDescriptor.Created sharedCreated;
+ protected SharedActivatableServiceDescriptor.Created activatableCreated;
+ protected ActivationGroupID groupCreated;
+
+ protected Object proxy;
+
+ protected String groupLog;
+
+ /**
+ * Default constructor.
+ */
+ public ServiceStarterAdmin() {
+ }
+
+ /**
+ * Takes the Config object for this test run so that the implementation
+ * can get access to property files and other config information.
+ *
+ * @param conf the Config object for this test run
+ */
+ public void setConfig(Config config) {
+ compatConfig = config;
+ compatSysConfig = config.getSysConfig();
+ log = compatConfig.getLog();
+ if (log == null) {
+ log = new PrintWriter(System.out, true);
+ }
+ }
+
+ /**
+ * Returns the address of the host the program is running on by
+ * looking up the property com.sun.jini.compat.defaultAdmin.address.
+ * If that property is not specified the default is the host the
+ * LDJ Kit harness is running on.
+ *
+ * @return the address of the program
+ */
+ public InetAddress getAddress() throws RemoteException {
+ String addr = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.defaultAdmin.address", null);
+ try {
+ if(addr == null) {
+ return InetAddress.getLocalHost();
+ } else {
+ return InetAddress.getByName(addr);
+ }
+ } catch(UnknownHostException uhe) {
+ throw new RemoteException(addr + " is an unknown host", uhe);
+ }
+ }
+
+ /**
+ * Using the <code>ServiceStarter</code>, starts the program(s)
+ * specified in the service starter configuration file specified
+ * by the property <code>com.sun.jini.compat.admin2.starterConfig</code>.
+ * The following strings are passed to this configuration as overrides:
+ * <ul>
+ * <li><code>com.sun.jini.compat.admin2.jskHome</code>=
+ * <value of <code>com.sun.jini.compat.admin2.jskHome</code> system property>
+ * <li><code>com.sun.jini.compat.admin2.javaHome</code>=
+ * <value of <code>com.sun.jini.compat.admin2.javaHome</code> system property>
+ * <li><code>com.sun.jini.compat.admin2.groupLog</code>=
+ * <return value of <code>getGroupLog()</code> method call>
+ * <li><code>com.sun.jini.compat.admin2.policyDir</code>=
+ * <value of the <code>com.sun.jini.compat.admin2.policyDir</code>
+ * system property or, if <code>null</code>, the value of
+ * <code>com.sun.jini.compat.installDir</code> property + "/policy">
+ * <li><code>com.sun.jini.compat.admin2.persistenceDir</code>=
+ * <return value of <code>getPersistenceDir()</code> method call>
+ * <li><code>com.sun.jini.compat.admin2.host</code>=
+ * <return value of <code>getAddress().getHostName()</code> method call>
+ * </ul>
+ * See the example configuration files in the <code>configs</code> sub-directory
+ * of the LDJ Kit. The <code>*-activatable.config</code> files
+ * are used by this Admin to test services in the Jini starter kit.
+ */
+ public synchronized void start() throws RemoteException {
+ String starterConfig = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.admin2.starterConfig", null);
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println("Using " + starterConfig
+ + " starter configuration file specified "
+ + "by the com.sun.jini.compat.admin2.starterConfig property");
+ }
+
+ String jskHome = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.admin2.jskHome", null);
+ String javaHome = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.admin2.javaHome", null);
+ String installDir = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.installDir", null);
+ String policyDir = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.admin2.policyDir", installDir + "/policy");
+
+ try {
+ Configuration config = ConfigurationProvider.getInstance(
+ new String[] { // config file followed by overrides
+ starterConfig,
+ "com.sun.jini.compat.admin2.jskHome=\"" + jskHome + "\"",
+ "com.sun.jini.compat.admin2.javaHome=\"" + javaHome + "\"",
+ "com.sun.jini.compat.admin2.groupLog=\""
+ + getGroupLog() + "\"",
+ "com.sun.jini.compat.admin2.policyDir=\"" + policyDir + "\"",
+ "com.sun.jini.compat.admin2.persistenceDir=\""
+ + getPersistenceDir() + "\"",
+ "com.sun.jini.compat.admin2.host=\""
+ + getAddress().getHostName() + "\""
+ },
+ this.getClass().getClassLoader());
+
+ ServiceDescriptor[] descs = (ServiceDescriptor[])
+ config.getEntry("com.sun.jini.start", "serviceDescriptors",
+ ServiceDescriptor[].class, null);
+
+ if (descs == null || descs.length == 0) {
+ log.println(starterConfig + " does not contain a "
+ + "com.sun.jini.start.serviceDescriptors entry; "
+ + "aborting");
+ System.exit(1);
+ }
+
+ // Non-activatable case: only 1 service descriptor must be present
+ if (descs.length == 1 &&
+ descs[0] instanceof NonActivatableServiceDescriptor)
+ {
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println(descs[0].toString());
+ }
+ nonActivatableCreated =
+ (NonActivatableServiceDescriptor.Created)
+ descs[0].create(config);
+ proxy = nonActivatableCreated.proxy;
+
+ // Activatable case: only 3 service descriptors must be present
+ } else if (
+ descs.length == 3 &&
+ descs[0] instanceof SharedActivationGroupDescriptor &&
+ descs[1] instanceof SharedActivatableServiceDescriptor &&
+ descs[2] instanceof SharedActivatableServiceDescriptor)
+ {
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println("SharedActivationGroupDescriptor: "
+ + descs[0].toString());
+ }
+ groupCreated = (ActivationGroupID) descs[0].create(config);
+
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println("SharedActivatableServiceDescriptor:"
+ + descs[1].toString());
+ }
+ sharedCreated = (SharedActivatableServiceDescriptor.Created)
+ descs[1].create(config);
+
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println("SharedActivatableServiceDescriptor: "
+ + descs[2].toString());
+ }
+ activatableCreated =
+ (SharedActivatableServiceDescriptor.Created)
+ descs[2].create(config);
+
+ proxy = activatableCreated.proxy;
+
+ } else {
+ log.println(starterConfig + " contains wrong number "
+ + "or type of ServiceDescriptors; aborting");
+ System.exit(1);
+ }
+
+ } catch (Exception e) {
+ if (compatConfig.getDebugLevel() >= Config.ERROR) {
+ log.println("Service creation exception: " + e);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Stops the program.
+ *
+ * If the program is activatable and implements
+ * <code>net.jini.admin.Administrable</code> and
+ * <code>com.sun.jini.admin.DestroyAdmin</code>
+ * then this method will make certain the program is
+ * unregistered with the activation system before returning.
+ */
+ public synchronized void stop() throws RemoteException {
+ int returnCode = ServiceDestroyer.DESTROY_SUCCESS;
+ try {
+
+ // stop non-activatable service (if non-null)
+ if (nonActivatableCreated != null) {
+ returnCode = ServiceDestroyer.destroy(
+ nonActivatableCreated.proxy);
+ nonActivatableCreated = null;
+ if (returnCode != ServiceDestroyer.DESTROY_SUCCESS) {
+ if (compatConfig.getDebugLevel() >= Config.ERROR) {
+ log.println("Warning: program may not have shutdown "
+ + "cleanly; destroy code is: " + returnCode);
+ }
+ }
+ }
+
+ // stop activatable service (if non-null)
+ if (activatableCreated != null) {
+ returnCode = ServiceDestroyer.destroy(activatableCreated,30);
+ activatableCreated = null;
+ }
+
+ // stop shared group (if non-null)
+ if (sharedCreated != null) {
+ ((SharedGroup)sharedCreated.proxy).destroyVM();
+ sharedCreated = null;
+ if (compatConfig.getDebugLevel() == Config.ALL) {
+ log.println("Destroyed activation group VM");
+ }
+ }
+ } catch (ActivationException ae) {
+ if (compatConfig.getDebugLevel() >= Config.ERROR) {
+ log.println("Warning: program may not have shutdown cleanly");
+ ae.printStackTrace(log);
+ }
+ }
+
+ // delete group log if present
+ if (groupLog != null) {
+ File groupLogFile = new File(groupLog);
+ File[] contents = groupLogFile.listFiles();
+ if (contents != null) {
+ for (int i = 0; i< contents.length; i++) {
+ contents[i].delete();
+ }
+ }
+ groupLogFile.delete();
+ }
+ }
+
+ /**
+ * Given a list of objects which are ServiceItems this method
+ * determines if any of them are the program we are testing. It
+ * does this by comparing the <code>service</code> field of each
+ * <code>ServiceItem</code> to the program's proxy returned from
+ * the ServiceStarter framework when the program was started.
+ *
+ * @param services the array of ServiceItems that need to be picked from
+ *
+ * @return the ServiceItem for the program being tested or null if
+ * none of the ServiceItems represent the program being tested
+ */
+ public synchronized ServiceItem pickService(ServiceItem[] services)
+ throws RemoteException
+ {
+ for (int i = 0; i < services.length; i++) {
+ if (services[i].service.equals(proxy)) {
+ return services[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a fully wild-carded template.
+ *
+ * @return the template
+ */
+ public ServiceTemplate getTemplate() throws RemoteException {
+ return new ServiceTemplate(null, null, null);
+ }
+
+ /**
+ * Returns the proxy for the lookup service being tested.
+ *
+ * @return lookup service proxy
+ */
+ public ServiceRegistrar getServiceRegistrar() throws RemoteException {
+ return (ServiceRegistrar) proxy;
+ }
+
+ /**
+ * Returns a randomized directory name within the
+ * <code>com.sun.jini.compat.scratchDir</code> that can be used
+ * as the group log directory. The returned directory name
+ * is saved so that this Admin can remove it later.
+ */
+ public String getGroupLog() {
+ String scratchDir = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.scratchDir", null);
+ groupLog = scratchDir + "/" + TestUtility.randomString(8);
+ return groupLog;
+ }
+
+ /**
+ * Returns a randomized directory name within the
+ * <code>com.sun.jini.compat.scratchDir</code> that can be used
+ * as the program's persistence directory.
+ */
+ public String getPersistenceDir() {
+ String scratchDir = compatSysConfig.getStringConfigVal(
+ "com.sun.jini.compat.scratchDir", null);
+ return scratchDir + "/" + TestUtility.randomString(8);
+ }
+}
Propchange: river/tck/src/com/sun/jini/compat/admin2/ServiceStarterAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/admin2/package.html
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/admin2/package.html?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/admin2/package.html (added)
+++ river/tck/src/com/sun/jini/compat/admin2/package.html Sat Jan 21 07:28:27 2012
@@ -0,0 +1,22 @@
+<!--
+ !
+ ! Copyright 2005, Sun Microsystems, Inc.
+ ! Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">
+ ! Apache License, Version 2.0</a>.
+ !
+ !-->
+<BODY BGCOLOR="white">
+
+This package contains admin implementations for the services that ship
+with the Jini(TM) Technology Starter Kit, v2.0 and later.
+
+These classes are provided as examples of how to
+write your own service's admin. Admins are used to automate the testing of a
+program using the Jini Technology Lookup, Discovery, and Join Compatibility Kit.
+
+
+@see <a href="../../../../../../writing-admin.html"><i>Implementing the LDJ Kit Admin Interface</i></a>
+@see <a href="../../../../../../running.html"><i>Running the Jini Technology Lookup, Discovery, and Join Compatibility Kit</i></a>
+
+</BODY>
+</HTML>
Propchange: river/tck/src/com/sun/jini/compat/admin2/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/constants/ThrowableConstants.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/constants/ThrowableConstants.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/constants/ThrowableConstants.java (added)
+++ river/tck/src/com/sun/jini/compat/constants/ThrowableConstants.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.constants;
+
+import java.io.ObjectStreamException;
+import java.rmi.RemoteException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.MarshalException;
+import java.rmi.UnmarshalException;
+import java.rmi.ServerException;
+import java.rmi.ServerError;
+
+/**
+ * Various constants useful in processing exceptions
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+public class ThrowableConstants {
+ /**
+ * Value returned by <code>retryable</code> to indicate that the
+ * passed <code>Throwable</code> does not provide any new
+ * information on the state of the object that threw it.
+ * @see #retryable
+ */
+ final static public int INDEFINITE = 0;
+
+ /**
+ * Value returned by <code>retryable</code> to indicate that the
+ * passed <code>Throwable</code> implies that retrying the
+ * operation that threw the <code>Throwable</code> with the same
+ * arguments and the same expected return value would not be
+ * fruitful.
+ * @see #retryable
+ */
+ final static public int BAD_INVOCATION = 1;
+
+ /**
+ * Value returned by <code>retryable</code> to indicate that the
+ * passed <code>Throwable</code> implies that any further
+ * operations on the object that threw the <code>Throwable</code>
+ * would not be fruitful.
+ * @see #retryable
+ */
+ final static public int BAD_OBJECT = 2;
+
+ /**
+ * Value returned by <code>retryable</code> to indicate that the
+ * passed <code>Throwable</code> was of a type that could not be
+ * classified.
+ * @see #retryable
+ */
+ final static public int UNCATEGORIZED = 3;
+
+ /**
+ * Attempt to classify the passed <code>Throwable</code> in terms of
+ * what it implies about the probability of success of future operations
+ * on the object that threw the exception.
+ *
+ * @return <code>INDEFINITE</code>, <code>BAD_INVOCATION</code>,
+ * or <code>BAD_OBJECT</code> if the exception is a
+ * <code>RuntimeException</code>, <code>Error</code>, or
+ * <code>java.rmi.RemoteException</code> depending on the details of
+ * the <code>Throwable</code>. Otherwise return <code>UNCATEGORIZED</code>
+ * @throws NullPointerException if the passed <code>Throwable</code> is
+ * <code>null</code>
+ */
+ public static int retryable(Throwable t) {
+ if (t == null)
+ throw new NullPointerException("Must pass a non-null Throwable");
+
+ if (t instanceof RuntimeException)
+ return BAD_OBJECT;
+
+ if (t instanceof Error) {
+ if ((t instanceof OutOfMemoryError) ||
+ (t instanceof LinkageError))
+ {
+ return INDEFINITE;
+ }
+
+ return BAD_OBJECT;
+ }
+
+ if (t instanceof RemoteException) {
+ final RemoteException re = (RemoteException)t;
+
+ if (re instanceof NoSuchObjectException)
+ return BAD_OBJECT;
+
+ final Throwable detail = re.detail;
+ if (detail == null)
+ return INDEFINITE;
+
+ if (re instanceof MarshalException ||
+ re instanceof UnmarshalException)
+ {
+ if (detail instanceof ObjectStreamException)
+ return BAD_INVOCATION;
+
+ return INDEFINITE;
+ }
+
+ if (re instanceof ServerException) {
+ return retryable(detail);
+ }
+
+ if (re instanceof ServerError) {
+ return retryable(detail);
+ }
+
+ return INDEFINITE;
+ }
+
+ return UNCATEGORIZED;
+
+ }
+}
Propchange: river/tck/src/com/sun/jini/compat/constants/ThrowableConstants.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/AbstractRunner.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/AbstractRunner.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/AbstractRunner.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/AbstractRunner.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,472 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+// java.util
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
+// java.io
+import java.io.PrintWriter;
+
+// com.sun.jini
+import com.sun.jini.system.MultiCommandLine;
+import com.sun.jini.system.CommandLine.BadInvocationException;
+import com.sun.jini.system.CommandLine.HelpOnlyException;
+import com.sun.jini.compat.harness.BasicAdmin;
+
+/**
+ * This class is a base class for implementing harness (or "runner") classes
+ * for the LDJ Kit tests. This class defines methods, both concrete
+ * and abstract, that handle the functions involved with running a set
+ * of tests identified on the command line through either a list of individual
+ * test name or categories (or both); functions such as setting up the
+ * the top-level configuration of the test harness, identifying the tests
+ * to execute on the requested run, and actually initiating the tests
+ * to run.
+ */
+public abstract class AbstractRunner {
+
+ private static final int INVALID_ADMIN = -3;
+ private static final int INVALID_CATEGORY = -2;
+ private static final int INVALID_TEST = -1;
+ private static final int VALID_TEST = 0;
+ private static final int EXCLUDED_TEST = 1;
+ private static final int EXCLUDED_CATEGORY = 2;
+
+ private List testNames;
+ private String[] arguments;
+ private List categories;
+ private boolean dups;
+ private int testTries = 0;
+ private PrintWriter log;
+
+ private List xCategories = new ArrayList(11); //excluded categories
+ private List xTestNames = new ArrayList(11); //excluded tests
+
+ private final static int maxTestCount = 100;
+ private Config tConfig = null;
+
+ /**
+ * Constructs a new instance of this class. This constructor parses
+ * the command line, sets up the top-level configuration for the
+ * requested test run, and identifies the tests to run.
+ *
+ * @param args <code>String</code> array containing the command line
+ * arguments
+ * @param log an instance of <code>java.io.PrintWriter</code>
+ * through which all test output is written
+ */
+ public AbstractRunner(String[] args, PrintWriter log) {
+ this.log = log;
+ arguments = args;
+ MultiCommandLine mcl = new MultiCommandLine(arguments);
+ try {
+ String testString = mcl.getString("tests", null);
+ boolean gui = mcl.getBoolean("gui");
+ dups = !mcl.getBoolean("noduplicates");
+ String cats = mcl.getString("categories", null);
+ if (cats == null)
+ cats = mcl.getString("category", null);
+
+ String configFile = null;
+ try {
+ String[] ops = mcl.getOperands();
+ if (ops.length >= 1)
+ configFile = ops[0];
+ } catch (HelpOnlyException hoe) {
+ usage();
+ System.exit(1);
+ }
+
+ tConfig = doConfig(configFile,log);
+
+ log.println();
+ log.println("---------------------------");
+ log.println("CONFIGURATION FILE:");
+ log.println();
+ log.println(" " + configFile);
+ log.println();
+
+ if (cats == null) {
+ SysConfig sys = tConfig.getSysConfig();
+ cats = sys.getStringConfigVal("com.sun.jini.compat.categories",
+ null);
+ if (cats == null) {
+ log.println("ERROR: The category of the "
+ + "of the product being tested must either "
+ + "be specified on the command line by "
+ + "-categories cat1,cat2,etc.. or "
+ + "by the property "
+ + "com.sun.jini.compat.categories");
+ System.exit(1);
+ }
+ }
+
+ setupCategories(cats);
+ testNames = new ArrayList();
+
+ String xTestsString = mcl.getString("xtests", null);
+ setupXTests(xTestsString);
+ String xCats = mcl.getString("xcategories", null);
+ setupXCategories(xCats);
+
+ log.println("---------------------------");
+ log.println("SETTING UP THE TEST LIST:");
+ log.println();
+ // If there are no arguments assume the user wants all the tests.
+ if (testString == null) {
+ addAllTests();
+ } else {
+ addTests(testString);
+ }
+ } catch (BadInvocationException bie) {
+ usage();
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Returns the categories that were input for the current test run either
+ * on the command line, or in the configuration file.
+ *
+ * @return <code>String</code> array containing the categories that were
+ * input for the current test run either on the command line, or
+ * in the configuration file.
+ */
+ public String[] getRequestedCategories() {
+ return ((String[])categories.toArray(new String[categories.size()]));
+ }
+
+ /**
+ * Abstract method which allows sub-classes of this class to define
+ * the mechanism for retrieving the information contained in the top-level
+ * configuration property file identified by the <code>configFile</code>
+ * parameter, and for storing that information in the return value for
+ * access throughout the test run.
+ *
+ * @param configFile the name of the property file containing the
+ * top-level configuration information for all
+ * tests to be executed on the current run
+ * @param log an instance of <code>java.io.PrintWriter</code>
+ * through which all test output is written
+ *
+ * @return the Config object that stores the retrieved information
+ */
+ protected abstract Config doConfig(String configFile, PrintWriter log);
+
+ /**
+ * Gives subclasses access to the Config object.
+ *
+ * @return the Config object
+ */
+ protected Config getConfig() {
+ return tConfig;
+ }
+
+ /**
+ * Abstract method which allows sub-classes of this class to define
+ * the action to take when all possible tests have been requested
+ * for the current test run.
+ *
+ * @throws com.sun.jini.system.CommandLine.BadInvocationException to
+ * allow for the case where a particular harness will not
+ * (or cannot) handle a request to run all possible tests
+ */
+ protected abstract void addAllTests() throws BadInvocationException;
+
+ /**
+ * Abstract method which allows sub-classes of this class to define
+ * the harness usage message that is printed to standard output.
+ */
+ protected abstract void usage();
+
+ private void setupCategories(String cats) {
+ categories = new ArrayList();
+ StringTokenizer st = new StringTokenizer(cats, ",");
+ while (st.hasMoreTokens()) {
+ categories.add(st.nextToken().toLowerCase());
+ }
+ }
+
+ private void setupXCategories(String xCats) {
+ if (xCats == null) {
+ return;
+ }
+ StringTokenizer st = new StringTokenizer(xCats, ",");
+ while (st.hasMoreTokens()) {
+ xCategories.add(st.nextToken().toLowerCase());
+ }
+ }
+
+ private void setupXTests(String xTests) {
+ if (xTests == null) {
+ return;
+ }
+ StringTokenizer st = new StringTokenizer(xTests, ",");
+ while (st.hasMoreTokens()) {
+ xTestNames.add(st.nextToken().toLowerCase());
+ }
+ }
+
+ private void addTests(String testList) {
+ // to make sure we are not in some kind of property loop
+ if (testTries > maxTestCount) {
+ return;
+ }
+
+ // if we haven't hit our limit and we count this as a try
+ testTries++;
+ String nextList = null;
+ SysConfig sysConfig = tConfig.getSysConfig();
+
+ // if it starts with "set:" it's a subset
+ if (testList.substring(0,4).toLowerCase().equals("set:")) {
+ StringTokenizer st = new StringTokenizer(testList, ",");
+ String subset = st.nextToken().substring(4);
+ nextList = System.getProperty(subset);
+ if (nextList == null) {
+ nextList =
+ sysConfig.getStringConfigVal(subset, null);
+ }
+ if (nextList != null) {
+ addTests(nextList);
+ if (st.hasMoreTokens())
+ addTests(testList.substring(subset.length() + 5));
+ }
+ } else {
+ StringTokenizer st = new StringTokenizer(testList, ",");
+ String className = st.nextToken();
+ // try to add the test to the list to execute
+ addTest(className);
+ if (st.hasMoreTokens()) {
+ nextList = testList.substring(className.length() + 1);
+ addTests(nextList);
+ }
+ }
+ }
+
+ private int validTest(Test test) {
+ try {
+ // Determine if the test been excluded by name
+ String testName = new String((test.getClass()).toString()).
+ substring("class ".length()).toLowerCase();
+ if (xTestNames.contains(testName))
+ return EXCLUDED_TEST;
+
+ String[] cats = test.getCategories();
+
+ // Determine if the test belongs to any excluded category
+ for (int i = 0; i < cats.length; i++) {
+ if (xCategories.contains(cats[i]))
+ return EXCLUDED_CATEGORY;
+ }//end loop(i)
+
+ // Determine if test's categories are valid
+ boolean good = false;
+ for (int i = 0; i < cats.length; i++) {
+ if (categories.contains(cats[i])) {
+ good = true;
+ break;
+ }
+ }
+ if (!good) {
+ return INVALID_CATEGORY;
+ }
+
+ Class[] admins = test.getRequiredAdmins();
+ BasicAdmin ba = tConfig.getAdmin();
+ Class baClass = ba.getClass();
+ for (int i = 0; i < admins.length; i++) {
+ if (!admins[i].isAssignableFrom(baClass)) {
+ return INVALID_ADMIN;
+ }
+ }
+ return VALID_TEST;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return INVALID_TEST;
+ }
+
+ /**
+ * Method called after each test to run a command in a separate process.
+ * As an example, this method is useful to execute a diagnostic
+ * command script to determine system resources after each test.
+ * <p>
+ * The command to run is specified by the property
+ * com.sun.jini.qa.runCommandAfterEachTest. If this property is null or
+ * not specified, then no command is run.
+ * <p>
+ * The method returns once the command finishes. Any exception thrown
+ * by trying to run the command is ignored.
+ */
+ private void runCommandAfterEachTest() {
+ try {
+ String command = getConfig().getSysConfig().getStringConfigVal(
+ "com.sun.jini.qa.runCommandAfterEachTest",null);
+ if (command != null) {
+ Process process = Runtime.getRuntime().exec(command);
+ process.waitFor();
+ }
+ } catch (Exception ignore) {}
+ }
+
+ /**
+ * Attempt to add the test implemented by className to the current
+ * set of tests.
+ */
+ protected void addTest(String className) {
+ Test test = null;
+ try {
+ Class c = Class.forName(className);
+ test = (Test)c.newInstance();
+ } catch (Exception e) {
+ log.println(" Skipping test: " + className);
+ log.println(" Reason: cannot find/call a public no "
+ + "argument constructor for " + className);
+ log.println(" Exception: " + e);
+ return;
+ }
+
+ int testState = validTest(test);
+ if (testState == VALID_TEST) {
+ if (!dups && testNames.contains(className)) {
+ log.println(" Skipping test: " + className);
+ log.println(" Reason: duplicate test");
+ return;
+ }
+ log.println(" Adding test: " + className);
+ testNames.add(className);
+ } else if ((testState == EXCLUDED_TEST) ||
+ (testState == EXCLUDED_CATEGORY) ) {
+ log.println(" Excluding test: " + className);
+ } else if (testState == INVALID_CATEGORY) {
+ log.println(" Skipping test: " + className);
+ log.println(" Reason: category mismatch");
+ log.print(" Categories selected for this run: ");
+ for (int j = 0; j < categories.size(); j++) {
+ log.print(categories.get(j) + " ");
+ }
+ log.println();
+ log.print(" Categories this test applies to: ");
+ String[] testCategories = test.getCategories();
+ for (int j = 0; j < testCategories.length; j++) {
+ log.print(testCategories[j] + " ");
+ }
+ log.println();
+ } else if (testState == INVALID_ADMIN) {
+ log.println(" Skipping test: " + className);
+ log.println(" Reason: required Admin mismatch");
+ } else { // testState == INVALID_TEST
+ log.println(" Skipping test: " + className);
+ log.println(" Reason: invalid test");
+ } //endif(validTest)
+ } //end addTest
+
+ /**
+ * This method batch runs all of the tests and displays their results.
+ *
+ * @return true if all started tests complete and pass; false if either
+ * one or more of the started tests fail or does not complete
+ */
+ public boolean runTests() {
+ log.println("---------------------------");
+ log.println("STARTING TO RUN THE TESTS");
+ log.println();
+ log.println();
+ ArrayList testList = new ArrayList(testNames.size());
+ ArrayList statusList = new ArrayList(testNames.size());
+ int numPassed = 0;
+ int numFailed = 0;
+ for (int i = 0; i < testNames.size(); i++) {
+ String className = (String)testNames.get(i);
+ Test test = null;
+ try {
+ Class c = Class.forName(className);
+ test = (Test)c.newInstance();
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.println();
+ log.println("Error instantiating class: " + className);
+ continue;
+ } //end try
+ Status status = null;
+ try {
+ log.println("Running " + className + "...");
+ log.println("Time is " + new Date());
+ if (!tConfig.isOfficial()) {
+ log.println("UNOFFICIAL TEST RUN");
+ }
+
+ test.setConfig(tConfig);
+ test.setup(arguments);
+ status = test.run(arguments);
+
+ if (status.getState()) {
+ numPassed++;
+ } else {
+ numFailed++;
+ }
+ testList.add(className);
+ statusList.add(status);
+ } catch (Throwable e) {
+ status = Status.failed(Status.ENV,
+ "Exception caught by Runner: " + e);
+ if (tConfig.getDebugLevel() >= Config.ERROR) {
+ e.printStackTrace(log);
+ }
+ } finally {
+ test.tearDown();
+ status.displayResults(log);
+ runCommandAfterEachTest();
+ } //end try
+ try {
+ Thread.sleep(10000); //wait 10 seconds between tests
+ } catch (InterruptedException ignore) {
+ }
+ log.println();
+ log.println("--------------------------");
+ log.println();
+ log.flush();
+ } //end loop
+ log.println("Summary --");
+ log.println();
+ for (int i = 0; i < testList.size(); i++) {
+ String testName = (String)testList.get(i);
+ Status testStatus = (Status)statusList.get(i);
+ log.println(testName);
+ testStatus.displayResults(log);
+ log.println("--------------------------");
+ log.flush();
+ }
+ log.println();
+ log.println("# of tests started = " + testNames.size());
+ log.println("# of tests completed = " + testList.size());
+ log.println("# of tests passed = " + numPassed);
+ log.println("# of tests failed = " + numFailed);
+ log.println("--------------------------");
+ log.println();
+ log.flush();
+ return (numFailed == 0 && testNames.size() == testList.size());
+ } //end runTests
+
+}
Propchange: river/tck/src/com/sun/jini/compat/harness/AbstractRunner.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/BasicAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/BasicAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/BasicAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/BasicAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+import java.rmi.RemoteException;
+import java.net.InetAddress;
+import com.sun.jini.compat.harness.Config;
+
+/**
+ * An interface for basic administration of any kind of program. All
+ * Admin interfaces subclass from this one. If someone wishes to automate
+ * the testing of their program they need to implement this
+ * interface and one of it's subinterfaces depending on the program
+ * category. The implementation must also have a no argument
+ * constructor or a constructor that takes a <code>String</code>
+ * as it's only argument.
+ */
+public interface BasicAdmin {
+
+ /**
+ * Passes a config object to the admin so that implementations of the
+ * admin can get access to configuration information, such as
+ * config files.
+ *
+ * @param conf the configuration object
+ */
+ void setConfig(Config conf);
+
+ /**
+ * Start the Jini(TM) technology features of the program.
+ */
+ void start() throws RemoteException;
+
+ /**
+ * Gets the internet address of the host where the program is
+ * being run.
+ *
+ * @return the address
+ */
+ InetAddress getAddress() throws RemoteException;
+
+ /**
+ * Stop the Jini(TM) technology features of the program completely including
+ * removing the program from activation and resetting any
+ * persistence these features require.
+ */
+ void stop() throws RemoteException;
+}
Propchange: river/tck/src/com/sun/jini/compat/harness/BasicAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/BasicClientAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/BasicClientAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/BasicClientAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/BasicClientAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+import java.rmi.RemoteException;
+import java.net.InetAddress;
+
+/**
+ * An interface for the basic administration of a client.
+ * Developers wishing to automate the testing of their client need to
+ * implement this interface. A Jini(TM) technology client is an program
+ * that goes through discovery to find a lookup service. Currently this
+ * is mostly a marker interface with the name of the category included.
+ * The <code>BasicClientAdmin</code> implementation class is expected
+ * to have a constructor that either takes no arguments or takes
+ * a <code>String</code> as an argument.
+ */
+public interface BasicClientAdmin extends BasicAdmin{
+ public final static String CATEGORY = "client";
+}
Propchange: river/tck/src/com/sun/jini/compat/harness/BasicClientAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/BasicLookupAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/BasicLookupAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/BasicLookupAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/BasicLookupAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+import java.rmi.RemoteException;
+import net.jini.core.lookup.ServiceRegistrar;
+
+/**
+ * An interface for basic administration of a lookup. Developers
+ * wishing to automate the testing of their lookup should write
+ * a class that implements this interface and provides appropriate
+ * method implementations for the service it administers. The
+ * <code>BasicLookupAdmin</code> implementation class is expected
+ * to have a constructor that either takes no arguments or takes
+ * a <code>String</code> as an argument.
+ */
+public interface BasicLookupAdmin extends BasicAdmin{
+ public final static String CATEGORY = "lookup";
+
+ /**
+ * Returns the ServiceRegistrar from an already started Lookup.
+ * If there are any problems getting the ServiceRegistrar it
+ * throws a RemoteException.
+ *
+ * @return a ServiceRegistrar for the lookup being tested.
+ */
+ public ServiceRegistrar getServiceRegistrar()
+ throws RemoteException;
+}
+
+
Propchange: river/tck/src/com/sun/jini/compat/harness/BasicLookupAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/BasicServiceAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/BasicServiceAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/BasicServiceAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/BasicServiceAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+import java.net.InetAddress;
+
+import java.rmi.RemoteException;
+import net.jini.core.lookup.ServiceItem;
+import net.jini.core.lookup.ServiceTemplate;
+
+/**
+ * An interface for basic administration of a service. Developers
+ * wishing to automate the testing of their service should write
+ * a class that implements this interface and provides appropriate
+ * method implementations for the service it administers. The
+ * <code>BasicServiceAdmin</code> implementation class is expected
+ * to have a constructor that either takes no arguments or takes
+ * a <code>String</code> as an argument.
+ */
+public interface BasicServiceAdmin extends BasicAdmin{
+ public final static String CATEGORY = "service";
+
+ /**
+ * Given an array of service proxy objects, this method
+ * should return the service associated with this admin. If the
+ * associated service is not found in the <code>services</code>
+ * array, then this method should return <code>null</code>.
+ *
+ * @param services the array of <code>ServiceItem</code> objects
+ * from which to choose
+ * @return the <code>ServiceItem</code> for the service being tested,
+ * or <code>null</code>
+ */
+ ServiceItem pickService(ServiceItem[] services) throws RemoteException;
+
+ /**
+ * Return a <code>ServiceTemplate</code> that can be used to identify
+ * the service. This helps to filter out unnecessary notifications.
+ *
+ * @return the template that best matches the service being tested
+ */
+ ServiceTemplate getTemplate() throws RemoteException;
+}
+
+
Propchange: river/tck/src/com/sun/jini/compat/harness/BasicServiceAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/Config.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/Config.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/Config.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/Config.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,273 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+import java.lang.reflect.Constructor;
+import java.io.PrintWriter;
+import java.net.URL;
+
+/**
+ * This class processes and holds the configuration information for
+ * all the tests being run. The <code>Runner</code> generates
+ * a single Config and passes it to each test using the setConfig
+ * method on <code>Test</code>. This class provides the
+ * <code>InstrumentedClassServer</code>, the <code>SysConfig</code>
+ * and the <code>BasicAdmin</code> for the current run of the LDJ Kit.
+ * It also sets up the codebase and the security manager when it
+ * is constructed.
+ */
+public class Config {
+ private String propFilename = null;
+ private SysConfig sysConfig = null;
+ private BasicAdmin ba = null;
+ private InstrumentedClassServer ics = null;
+ private PrintWriter log;
+ private boolean official = true;
+
+ // Default timeout for quietTime is 10 minutes
+ private static final int QUIETTIMEOUT = 1000*60*10;
+ // Default timeout for failureTime is 30 seconds
+ private static final int FAILURETIMEOUT = 30000;
+
+ private int currentQuietTime = 0;
+
+ /**
+ * Debug Level that prints no extra information.
+ */
+ public static final int NONE = 0;
+
+ /**
+ * Debug Level that prints extra information when something
+ * unexpected happens.
+ */
+ public static final int ERROR = 1;
+
+ /**
+ * Debug Level that prints extra information throughout the run.
+ */
+ public static final int ALL = 2;
+
+ /*
+ * The default class name for the implementation class of the
+ * service admin.
+ */
+ private static final String defaultAdminClass =
+ "com.sun.jini.compat.harness.DefaultAdmin";
+
+ /*
+ * The class name for the basic service admin interface
+ */
+ private static final String adminInterface =
+ "com.sun.jini.compat.harness.BasicAdmin";
+
+ /**
+ * Constructor for the Config class. It does all the
+ * precalculations necessary to provide configuration
+ * information.
+ *
+ * @param pfn the path/filename of the config property file
+ * @param classServer a reference to a currently running
+ * <code>InstrumentedClassServer</code>
+ * @param log an instance of <code>java.io.PrintWriter</code>
+ * through which all test output is written
+ */
+ public Config(String pfn, InstrumentedClassServer classServer,
+ PrintWriter log)
+ throws Exception
+ {
+ this.log = log;
+ propFilename = new String(pfn);
+ sysConfig = new SysConfig(propFilename);
+
+ System.setSecurityManager(new java.rmi.RMISecurityManager());
+
+ ics = classServer;
+ System.setProperty("java.rmi.server.codebase",
+ ics.getCodeURL().toString() + "compat-dl.jar");
+ setupAdmin();
+
+ currentQuietTime =
+ sysConfig.getIntConfigVal("com.sun.jini.compat.unofficialQuietTime",
+ QUIETTIMEOUT);
+ if(currentQuietTime < QUIETTIMEOUT)
+ official = false;
+ }
+
+ /**
+ * Constructor for the Config class. It does
+ * precalculations necessary to provide configuration
+ * information but does not specify a class server
+ * nor does it set the Quiet Time needed by the LDJ Kit.
+ *
+ * @param pfn the path/filename of the config property file
+ * @param log an instance of <code>java.io.PrintWriter</code>
+ * through which all test output is written
+ */
+ public Config(String pfn, PrintWriter log) throws Exception {
+ this.log = log;
+ propFilename = new String(pfn);
+ sysConfig = new SysConfig(propFilename);
+ System.setSecurityManager(new java.rmi.RMISecurityManager());
+ setupAdmin();
+ }
+
+ private void setupAdmin() throws Exception {
+ String adminClassName = sysConfig.getStringConfigVal(
+ "com.sun.jini.compat.adminClass",
+ defaultAdminClass);
+ String adminArg = sysConfig.getStringConfigVal(
+ "com.sun.jini.compat.adminArg", null);
+
+ try {
+ Class adminClass = Class.forName(adminClassName);
+ Class basicAdminInterface = Class.forName(adminInterface);
+ if(!basicAdminInterface.isAssignableFrom(adminClass)) {
+ throw new Exception("Administration class "+
+ "specified in the config file "+
+ "must implement "+ adminInterface);
+ }
+
+ if(adminArg != null) {
+ Class[] constrArgClasses = { String.class };
+ Constructor[] all = adminClass.getConstructors();
+ Constructor stringConstr =
+ adminClass.getConstructor(constrArgClasses);
+ Object[] constrArgs = { adminArg };
+ ba =
+ (BasicAdmin)stringConstr.newInstance(constrArgs);
+ } else {
+ ba = (BasicAdmin)adminClass.newInstance();
+ }
+ ba.setConfig(this);
+ } catch(Exception e) {
+ throw new Exception("Problems getting Administration "+
+ "object for the service: "+e);
+ }
+ }
+
+ /**
+ * Method returns the class server for this run of the LDJ Kit.
+ *
+ * @return the class server
+ */
+ public InstrumentedClassServer getClassServer() {
+ return ics;
+ }
+
+ /**
+ * Method returns the <code>SysConfig</code> for this run of the
+ * LDJ Kit. It is used by tests to get access to the LDJ Kit property
+ * file.
+ *
+ * @return the <code>SysConfig</code>
+ */
+ public SysConfig getSysConfig() {
+ return sysConfig;
+ }
+
+ /**
+ * Method returns the admin for this run of the LDJ Kit. Depending on
+ * the program being tested this method will return different
+ * subclasses of <code>BasicAdmin</code>.
+ *
+ * @return the admin
+ */
+ public BasicAdmin getAdmin() {
+ return ba;
+ }
+
+ /**
+ * Returns the Quiet Time value. This is the value used for
+ * "negative" tests (when nothing should happen in a time interval).
+ * If the property <code>com.sun.jini.compat.unofficialQuietTime</code>
+ * is set, then its value is used. If this value is less than the
+ * official Quiet Time, then the run of the LDJ Kit is unofficial (used
+ * for testing/debugging purposes only).
+ *
+ * @return the Quite Time duration in milliseconds
+ */
+ public int getQuietTime() {
+ return currentQuietTime;
+ }
+
+ /**
+ * Returns the Failure Time value from SysConfig. This value
+ * is used to limit the time it takes for something to fail.
+ * It indicated the length of time you are willing to wait
+ * before you accept that the action is not going to happen.
+ *
+ * @return the Failure Time duration in milliseconds
+ */
+ public int getFailureTime() {
+ if(sysConfig == null)
+ throw new NullPointerException("SysConfig not initialized");
+ int to =
+ sysConfig.getIntConfigVal("com.sun.jini.compat.failureTime",
+ FAILURETIMEOUT);
+
+ return to;
+ }
+
+ /**
+ * Returns the log <code>PrintWriter</code> for this run of the LDJ Kit.
+ *
+ * @return the log <code>PrintWriter</code>
+ */
+ public PrintWriter getLog() {
+ return log;
+ }
+
+ /**
+ * Returns the current debug level of the LDJ Kit. Currently there
+ * are three debug levels:
+ * <p><ul>
+ * <li>NONE: no extra debug information is displayed
+ * <li>ERROR: extra debug information is only displayed during
+ * times when there are errors/problems
+ * <li>ALL: extra information is displayed throughout all parts of
+ * the run
+ * </ul><p>
+ * The debug level is obtained from the property:
+ * <code>com.sun.jini.compat.debugLevel</code>
+ *
+ * @return the debug level
+ */
+ public int getDebugLevel() {
+ if(sysConfig == null)
+ throw new NullPointerException("SysConfig not initialized");
+ String dl =
+ sysConfig.getStringConfigVal("com.sun.jini.compat.debugLevel",
+ "none").toLowerCase();
+
+ if(dl.equals("error"))
+ return ERROR;
+ else if(dl.equals("all"))
+ return ALL;
+ else
+ return NONE;
+ }
+
+ /**
+ * Returns whether this is an official run or not.
+ *
+ * @return <code>true</code> if this is an official run
+ */
+ public boolean isOfficial() {
+ return official;
+ }
+}
Propchange: river/tck/src/com/sun/jini/compat/harness/Config.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/ConfigProperties.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/ConfigProperties.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/ConfigProperties.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/ConfigProperties.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,300 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * When used in place of the class <code>java.util.Properties</code>, calls
+ * to this class' <code>getProperty</code> method will automatically perform
+ * pre-defined substitutions based on the following criteria:
+ *
+ * If test.name=aaaa.bbbb.cccc, then all occurrences of either $test.name
+ * or ${test.name} will be replaced with the value aaaa.bbbb.cccc
+ *
+ * Any value contained in single quotes is take literally. For example, if
+ * test.dollar='$', then the value of the property test.dollar is $.
+ *
+ * Substitutions are made within property values contained in double quotes,
+ * but no substitutions are made within property values contained in
+ * single quotes.
+ */
+public class ConfigProperties extends Properties {
+
+ /**
+ * Constructor that creates an empty property list with no default
+ * values.
+ */
+ public ConfigProperties() {
+ super(null);
+ }//end constructor
+
+ /**
+ * Constructor that creates an empty property list with the given default
+ * values.
+ *
+ * @param defaults <code>Properties</code> object containing the desired
+ * default values with which to construct this object.
+ */
+ public ConfigProperties(Properties defaults) {
+ super(defaults);
+ }//end constructor
+
+
+ /**
+ * Searches this property list for the property corresponding to the given
+ * <code>key</code> parameter. If the key is not found in this property
+ * list, the default property list and its defaults are then checked
+ * (recursively). This method returns <code>null</code> if the property is
+ * not found in any of the property lists checked. If the property is
+ * found, then any pre-defined substitutions are made and the result is
+ * returned.
+ *
+ * @param key <code>String</code> containing the property key whose
+ * corresponding value is to be retrieved and returned.
+ *
+ * @return <code>String</code> containing the property value corresponding
+ * to the given <code>key</code> parameter, with all substitutions
+ * made in the appropriate manner, or <code>null</code> if
+ * property not found
+ */
+ public String getProperty(String key) {
+ try {
+ return resolve(lookup(key));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }//end getProperty
+
+ /**
+ * Searches this property list for the property corresponding to the given
+ * <code>key</code> parameter. If the key is not found in this property
+ * list, the default property list and its defaults are then checked
+ * (recursively). If the property is not found in any of the property
+ * lists checked, the value in the <code>defaultValue</code> parameter,
+ * with all appropriate substitutions, is returned. If the property is
+ * found, then any pre-defined substitutions are made and the result is
+ * returned.
+ *
+ * @param key <code>String</code> containing the property key
+ * whose corresponding value is to be retrieved and
+ * returned.
+ * @param defaultValue <code>String</code> containing the value to return
+ * if no property value can be found in any of the
+ * property lists.
+ *
+ * @return <code>String</code> containing the property value corresponding
+ * to the given <code>key</code> parameter, with all substitutions
+ * made in the appropriate manner.
+ */
+ public String getProperty(String key, String defaultValue) {
+ try {
+ String val = getProperty(key); // val is already resolved
+ return ((val == null) ? resolve(defaultValue) : val);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }//end getProperty
+
+
+ /**
+ * Resolves a value in the environment by splitting it into words and
+ * performing pre-defined substitutions on it. White-space separates
+ * words except inside quoted strings.
+ *
+ * `<code>$<em>name</em></code>' and `<code>${<em>name</em>}</code>' are
+ * replaced by the result of calling `lookup(<em>name</em>)'.
+ *
+ * `<code>$/</code>' is replaced by the platform-specific file separator;
+ * `<code>$:</code>' is replaced by the platform-specific path separator;
+ *
+ * `<code>$$</code>' is replaced by a single `$'.
+ *
+ * No substitutions are performed inside single-quoted strings;
+ * $ substitutions are performed in double-quoted strings.
+ *
+ * @arg s <code>String</code> containing the value to be resolved
+ *
+ * @return <code>String</code> containing the result after the
+ * appropriate substitution(s) are made
+ *
+ * @throws java.lang.Exception typically, this exception occurs when there
+ * is a problem resolving the value of the input argument.
+ */
+ public String resolve(String s) throws Exception {
+ if (s == null) return s;
+ StringBuffer current = new StringBuffer(64);
+ char term = 0; // 0 => top level
+ // ' ' => inside word
+ char c = 0;
+ iLoop:
+ for (int i = 0;i < s.length(); i++) {
+ c = s.charAt(i);
+ switch (c) {
+ case '#':
+ /* # at top level introduces comment to end of line and
+ * terminates command (if found); otherwise, it goes into
+ * the current word
+ */
+ if (term == 0 || term ==' ') {
+ break iLoop;
+ } else {
+ current.append(c);
+ }
+ break;
+
+ case '\'':
+ case '\"':
+ /* string quotes at top level begin/end a matched pair;
+ * otherwise they are part of it
+ */
+ if (term == 0 || term == ' ') {
+ term = c; // start matched pair
+ } else if (term == c) {
+ term = ' '; // end matched pair
+ } else {
+ current.append(c); // put character in string
+ }
+ break;
+ case '$':
+ /* dollar introduces a name to be substituted, provided
+ * it does not appear in single quotes.
+ *
+ * Special values: $/ is File.separatorChar
+ * $: is File.pathSeparatorChar
+ * $$ is $
+ */
+ if (term != '\'') {
+ StringBuffer buf = new StringBuffer();
+ String name = null;
+ try {
+ c = s.charAt(++i);
+ switch (c) {
+ case '/':
+ current.append(File.separatorChar);
+ continue iLoop;
+ case ':':
+ current.append(File.pathSeparatorChar);
+ continue iLoop;
+ case '$':
+ current.append('$');
+ continue iLoop;
+ case '{':
+ c = s.charAt(++i);
+ while (c != '}') {
+ buf.append(c);
+ c = s.charAt(++i);
+ }
+ name = lookup(buf.toString());
+ break;
+ default:
+ if (isNameChar(c)) {
+ while( i < s.length()
+ && isNameChar(s.charAt(i)) )
+ {
+ buf.append(s.charAt(i++));
+ }//end loop
+ i--;
+ } else {
+ throw new Exception
+ ("bad $ expression: `$" + c + "'");
+ }
+ name = lookup(buf.toString());
+ }//end switch
+ String val = resolve(name);
+ /* only start a new word if there is something to
+ * substitute
+ */
+ if (val != null) {
+ if (term == 0) term = ' ';
+ current.append(val);
+ }
+ } catch (IndexOutOfBoundsException e) {
+ //e.printStackTrace();
+ throw new Exception("bad $ expression");
+ }
+ } else {
+ current.append(c);
+ }//endif
+ break;
+ case ' ':
+ /* space is skipped if not in a word; otherwise it goes
+ * into the current word
+ */
+ if (term != 0) current.append(c);
+ break;
+ case '\t':
+ /* tab is skipped if not in a word; if in a word and term
+ * is space, then terminate it; otherwise it goes into
+ * the current word
+ */
+ if (term != 0) {
+ if (term == ' ') {
+ term = 0;
+ } else {
+ current.append(c);
+ }
+ }
+ break;
+ default:
+ /* other characters start a word if needed, then go into
+ * the word
+ */
+ if (term == 0) term = ' ';
+ current.append(c);
+ break;
+ }//end switch
+ }//end loop(i)
+ /* the end has been reached; if a word has been started, finish it */
+ return current.toString();
+ }//end resolve
+
+ /* Returns the property value corresponding to the given <code>key</code>
+ * parameter without performing any substitution,
+ *
+ * @param key <code>String</code> containing the property key whose
+ * corresponding value is to be retrieved and returned.
+ *
+ * @return <code>String</code> containing the property value corresponding
+ * to the given <code>key</code> parameter.
+ */
+ private String lookup(String key) {
+ return super.getProperty(key);
+ }//end lookup
+
+ /* Determines if the given character is one of the characters associated
+ * with the dollar sign ($) substitution symbol.
+ *
+ * @param c <code>char</code> containing the character to analyze.
+ *
+ * @return <code>true</code> if the given character is one of the
+ * characters associated with the dollar sign ($) substitution
+ * symbol; <code>false</code> otherwise.
+ */
+ private static boolean isNameChar(char c) {
+ return ( Character.isUpperCase(c)
+ || Character.isLowerCase(c)
+ || Character.isDigit(c)
+ || (c == '_')
+ || (c == '.') );
+ }//end isNameChar
+
+}//end class ConfigProperties
Propchange: river/tck/src/com/sun/jini/compat/harness/ConfigProperties.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/DefaultAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DefaultAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DefaultAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DefaultAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.sun.jini.compat.harness;
+import java.rmi.RemoteException;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import com.sun.jini.compat.harness.Config;
+
+/**
+ * An implementation of the BasicAdmin interface. This
+ * implementation is not program specific and it is not automated. It
+ * asks the person running the tests to manually start and stop the
+ * program being tested. Also it uses a property called:
+ * com.sun.jini.compat.defaultAdmin.address to specify the host the
+ * client is running on. If the property is not specified the default
+ * is the host the LDJ Kit harness is running on.
+ */
+public class DefaultAdmin implements BasicAdmin {
+ private String userMessage = null;
+ private Config config = null;
+
+ /**
+ * A basic no-arg constructor.
+ */
+ public DefaultAdmin() {
+ }
+
+ /**
+ * A constructor that takes a message to
+ * be displayed with the various user input requests.
+ *
+ * @param message a message to be displayed with the user input
+ * requests.
+ */
+ public DefaultAdmin(String message) {
+ userMessage = new String(message);
+ }
+
+ /**
+ * See comments for <code>BasicAdmin</code>.
+ */
+ public void setConfig(Config conf) {
+ config = conf;
+ }
+
+ /**
+ * Returns the Config object for this run of the LDJ Kit.
+ *
+ * @return the Config object
+ */
+ protected Config getConfig() {
+ return config;
+ }
+
+ /**
+ * Wait for a character to be read in.
+ *
+ * @return the character read from <code>System.in</code>
+ */
+ protected char waitForChar() {
+ InputStreamReader isr = new InputStreamReader(System.in);
+ int readChar = -1;
+
+ try {
+ readChar = isr.read();
+ } catch(IOException ioe) {
+ System.err.println("Problem reading keys.");
+ }
+ return (char)readChar;
+ }
+
+ /**
+ * Prompt the user to start the program.
+ */
+ public synchronized void start() throws RemoteException {
+ System.out.println();
+ if(userMessage != null) {
+ System.out.println(userMessage);
+ }
+ System.out.println("Start the program now.");
+ System.out.print("Press Enter when program started: ");
+ waitForChar();
+ System.out.println("Testing....");
+ System.out.println();
+ }
+
+ /**
+ * Returns the address of the host the program is running on by
+ * looking up the property com.sun.jini.compat.defaultAdmin.address.
+ * If that property is not specified the default is the host the
+ * LDJ Kit harness is running on.
+ *
+ * @return the address of the program
+ */
+ public InetAddress getAddress() throws RemoteException {
+ SysConfig sysConfig = config.getSysConfig();
+
+ String addr = sysConfig.getStringConfigVal(
+ "com.sun.jini.compat.defaultAdmin.address",
+ null);
+ InetAddress ia = null;
+ try {
+ if(addr == null) {
+ ia = InetAddress.getLocalHost();
+ } else {
+ ia = InetAddress.getByName(addr);
+ }
+ } catch(UnknownHostException uhe) {
+ throw new RemoteException(addr + " is an unknown host", uhe);
+ }
+
+ return ia;
+ }
+
+ /**
+ * Prompt the user to stop the program.
+ */
+ public synchronized void stop() throws RemoteException {
+ System.out.println();
+ if(userMessage != null) {
+ System.out.println(userMessage);
+ }
+ System.out.println("Stop the program now.");
+ System.out.print("Press Enter when program stopped: ");
+ waitForChar();
+ System.out.println();
+ }
+}
Propchange: river/tck/src/com/sun/jini/compat/harness/DefaultAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/harness/DefaultClientAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DefaultClientAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DefaultClientAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DefaultClientAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.harness;
+
+import java.rmi.RemoteException;
+
+/**
+ * This class extends DefaultAdmin which currently provides all of the
+ * necessary functionality for testing clients.
+ */
+public class DefaultClientAdmin extends DefaultAdmin
+ implements BasicClientAdmin
+{
+ public DefaultClientAdmin() {
+ }
+}
+
+
Propchange: river/tck/src/com/sun/jini/compat/harness/DefaultClientAdmin.java
------------------------------------------------------------------------------
svn:eol-style = native