river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peter_firmst...@apache.org
Subject svn commit: r1634322 [21/41] - in /river/jtsk/skunk/qa_refactor/trunk: qa/src/com/sun/jini/qa/harness/ qa/src/com/sun/jini/test/impl/end2end/e2etest/ qa/src/com/sun/jini/test/impl/joinmanager/ qa/src/com/sun/jini/test/impl/mahalo/ qa/src/com/sun/jini/t...
Date Sun, 26 Oct 2014 13:17:31 GMT
Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/RenewingRemoteListener.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/RenewingRemoteListener.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/RenewingRemoteListener.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/RenewingRemoteListener.java Sun Oct 26 13:17:28 2014
@@ -1,151 +1,152 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.test.share;
-
-// java.*
-import java.rmi.RemoteException;
-import java.util.logging.Level;
-
-// net.jini
-import net.jini.core.event.RemoteEvent;
-import net.jini.core.event.UnknownEventException;
-import net.jini.core.lease.Lease;
-import net.jini.lease.ExpirationWarningEvent;
-import net.jini.lease.LeaseRenewalSet;
-
-import net.jini.export.Exporter;
-
-import com.sun.jini.qa.harness.QATestEnvironment;
-import com.sun.jini.qa.harness.QAConfig;
-import com.sun.jini.qa.harness.TestException;
-
-/**
- * RenewingRemoteListener keeps track of each RemoteEvent it
- * receives and if the event is an ExpirationWarningEvent it will attempt
- * to renew the lease.
- *
- * @author Steven Harris - SMI Software Development 
- */
-public class RenewingRemoteListener extends RememberingRemoteListener {
-    
-    /**
-     * the duration for renewing the set's lease 
-     */
-    protected long duration = 0;
-
-    /**
-     * If lease could not be renewed then the exception is stored here.
-     */
-    protected Throwable renewalException = null;
-
-    /**
-     * The last lease that was successfully renewed.
-     */
-    protected Lease lastLeaseRenewed = null;
-
-    /**
-     * Constructor requiring a renewal duration value and an Exporter.
-     * 
-     * @exception RemoteException
-     *          Remote initialization problem.  
-     */
-    public RenewingRemoteListener(Exporter exporter, long renewSetDur) 
-	     throws RemoteException {
-	super(exporter);
-	duration = renewSetDur;
-    }
-    
-    // inherit javadoc from parent class
-    public synchronized void notify(RemoteEvent theEvent) 
-           throws UnknownEventException, RemoteException {
-	super.notify(theEvent);
-	if (theEvent.getClass() == ExpirationWarningEvent.class) {
-	    LeaseRenewalSet set = (LeaseRenewalSet) theEvent.getSource();
-	    Lease lease = null;
-	    try {
-		set = (LeaseRenewalSet) 
-		      QAConfig.getConfig().prepare("test.normRenewalSetPreparer",
-							set);
-		lease = set.getRenewalSetLease();
-		lease =  (Lease)
-			 QAConfig.getConfig().prepare("test.normLeasePreparer",
-							   lease);
-	    } catch (TestException e) {
-		renewalException = e;
-		logger.log(Level.INFO,"Configuration error", e);
-		return;
-	    }
-	    // try to renew until lease is expired.
-	    boolean canBeRenewed = true;
-	    while (canBeRenewed) {
-		try {
-		    lease.renew(duration);
-		    renewalException = null;
-		    canBeRenewed = false;
-		    lastLeaseRenewed = lease;
-		    logger.log(Level.FINE, "Successfully renewed for " + duration +
-				           " milliseconds.");
-		} catch (Exception ex) {
-		    // assign the exception for later retrieval
-		    renewalException = ex;
-		    canBeRenewed = 
-			(lease.getExpiration() >= System.currentTimeMillis());
-		    if (canBeRenewed) {
-			logger.log(Level.FINE, "Failed to renew lease, trying again.");
-		    } else {
-			logger.log(Level.FINE, "Failed to renew lease, quitting.");
-		    }
-		    try {
-			Thread.sleep(250L); // try every quarter of a second
-		    } catch (InterruptedException interruptedEx) {
-			canBeRenewed = false; // okay we'll stop, I guess??
-		    }
-		}	    
-	    }
-	}
-    }
-
-    /**
-     * Return possible exception from renewal attempt.
-     * 
-     * <P>Notes:<BR>A value of null indicates renewal was successful.</P>
-     * 
-     * @return  the exception that resulted from failed renewal attempt.
-     */
-    public synchronized Throwable getRewewalException() {
-
-	return renewalException;
-    }
-
-    /**
-     * Return the last lease that was successfully renewed.
-     * 
-     * @return the last lease successfully renewed or null if none renewed yet.
-     * 
-     */
-    public synchronized Lease getLastLeaseRenewed() {
-	return lastLeaseRenewed;
-    }
-
-} // RenewingRemoteListener
-
-
-
-
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.test.share;
+
+// java.*
+import java.rmi.RemoteException;
+import java.util.logging.Level;
+
+// net.jini
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.event.UnknownEventException;
+import net.jini.core.lease.Lease;
+import net.jini.lease.ExpirationWarningEvent;
+import net.jini.lease.LeaseRenewalSet;
+
+import net.jini.export.Exporter;
+
+import com.sun.jini.qa.harness.QATestEnvironment;
+import com.sun.jini.qa.harness.QAConfig;
+import com.sun.jini.qa.harness.TestException;
+
+/**
+ * RenewingRemoteListener keeps track of each RemoteEvent it
+ * receives and if the event is an ExpirationWarningEvent it will attempt
+ * to renew the lease.
+ *
+ * @author Steven Harris - SMI Software Development 
+ */
+public class RenewingRemoteListener extends RememberingRemoteListener {
+    
+    /**
+     * the duration for renewing the set's lease 
+     */
+    protected long duration = 0;
+
+    /**
+     * If lease could not be renewed then the exception is stored here.
+     */
+    protected Throwable renewalException = null;
+
+    /**
+     * The last lease that was successfully renewed.
+     */
+    protected Lease lastLeaseRenewed = null;
+
+    /**
+     * Constructor requiring a renewal duration value and an Exporter.
+     * 
+     * @exception RemoteException
+     *          Remote initialization problem.  
+     */
+    public RenewingRemoteListener(Exporter exporter, long renewSetDur) 
+	     throws RemoteException {
+	super(exporter);
+	duration = renewSetDur;
+    }
+    
+    // inherit javadoc from parent class
+    public synchronized void notify(RemoteEvent theEvent) 
+           throws UnknownEventException, RemoteException {
+	super.notify(theEvent);
+	if (theEvent.getClass() == ExpirationWarningEvent.class) {
+	    LeaseRenewalSet set = (LeaseRenewalSet) theEvent.getSource();
+	    Lease lease = null;
+	    try {
+		set = (LeaseRenewalSet) 
+		      QAConfig.getConfig().prepare("test.normRenewalSetPreparer",
+							set);
+		lease = set.getRenewalSetLease();
+		lease =  (Lease)
+			 QAConfig.getConfig().prepare("test.normLeasePreparer",
+							   lease);
+	    } catch (TestException e) {
+		renewalException = e;
+		logger.log(Level.INFO,"Configuration error", e);
+		return;
+	    }
+	    // try to renew until lease is expired.
+	    boolean canBeRenewed = true;
+	    while (canBeRenewed) {
+		try {
+		    lease.renew(duration);
+		    renewalException = null;
+		    canBeRenewed = false;
+		    lastLeaseRenewed = lease;
+		    logger.log(Level.FINE, "Successfully renewed for " + duration +
+				           " milliseconds.");
+		} catch (Exception ex) {
+		    // assign the exception for later retrieval
+		    renewalException = ex;
+		    canBeRenewed = 
+			(lease.getExpiration() >= System.currentTimeMillis());
+		    if (canBeRenewed) {
+			logger.log(Level.FINE, "Failed to renew lease, trying again.");
+		    } else {
+			logger.log(Level.FINE, "Failed to renew lease, quitting.");
+		    }
+		    try {
+			Thread.sleep(250L); // try every quarter of a second
+		    } catch (InterruptedException interruptedEx) {
+                        Thread.currentThread().interrupt();
+			canBeRenewed = false; // okay we'll stop, I guess??
+		    }
+		}	    
+	    }
+	}
+    }
+
+    /**
+     * Return possible exception from renewal attempt.
+     * 
+     * <P>Notes:<BR>A value of null indicates renewal was successful.</P>
+     * 
+     * @return  the exception that resulted from failed renewal attempt.
+     */
+    public synchronized Throwable getRewewalException() {
+
+	return renewalException;
+    }
+
+    /**
+     * Return the last lease that was successfully renewed.
+     * 
+     * @return the last lease successfully renewed or null if none renewed yet.
+     * 
+     */
+    public synchronized Lease getLastLeaseRenewed() {
+	return lastLeaseRenewed;
+    }
+
+} // RenewingRemoteListener
+
+
+
+

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestBase.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestBase.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestBase.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestBase.java Sun Oct 26 13:17:28 2014
@@ -1,710 +1,717 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.test.share;
-
-
-// java.*
-import java.rmi.NoSuchObjectException;
-import java.rmi.RemoteException;
-import java.util.List;
-import java.util.Iterator;
-import java.util.ArrayList;
-
-// net.jini
-import net.jini.core.discovery.LookupLocator;
-import net.jini.core.lease.Lease;
-import net.jini.core.entry.Entry;
-import net.jini.core.event.EventRegistration;
-import net.jini.core.lease.UnknownLeaseException;
-import net.jini.core.lookup.ServiceRegistrar;
-import net.jini.lease.LeaseRenewalSet;
-import net.jini.space.JavaSpace;
-import net.jini.admin.Administrable;
-import net.jini.lookup.DiscoveryAdmin;
-
-// com.sun.jini
-import com.sun.jini.outrigger.JavaSpaceAdmin;
-import com.sun.jini.outrigger.AdminIterator;
-
-
-// com.sun.jini.qa
-import com.sun.jini.qa.harness.QATestEnvironment;
-import com.sun.jini.qa.harness.TestException;
-import com.sun.jini.qa.harness.QAConfig;
-import com.sun.jini.qa.harness.Test;
-
-import java.util.logging.Level;
-
-import net.jini.config.Configuration;
-import net.jini.config.ConfigurationException;
-import net.jini.security.ProxyPreparer;
-import org.apache.river.api.security.CombinerSecurityManager;
-
-/**
- * Base class for spaces QA tests.  Provides convenience functions for
- * logging failure, starting/finding and cleaning up the services under
- * test.  Also sets up a command line parser.
- * <p>
- * Tests provide an implementation of <code>runTest()</code> that
- * performs the appropriate tests, using
- * <code>specifyServices()</code> to indicate what services they need
- * for the test.  Test failure should be indicated by calling
- * <code>fail()</code> (or its close relative,
- * <code>setupFailure()</code>) Passing can be indicated by calling
- * <code>pass()</code> or by returning from <code>runTest()</code>
- * normally. Tests should not invoke <code>Status.exit()</code>
- * directly.
- * <p>
- * If a test needs to parse command line arguments it should override
- * <code>parse()</code> and use the <code>CmdLine</code> command line
- * parser provided in <code>line</code>.
- * <p>
- * If a test has to perform any post test cleanup it should override
- * <code>cleanup()</code>
- *
- * Command line arguments
- * <p>
- * <DL>
- * <DT>-external <var>jini-url</var><DD> The test will find the
- * necessary services though the designated lookup service. Normally
- * the test will start any necessary services with the exception of an
- * activation demon.
- *
- * <DT>-scrub<DD> Can be used with <code>-external</code>. The test
- * will attempt to put the services in a "clean" state before running
- * the test.  Note this is currently implemented only for JavaSpaces.
- *
- * <DT>-administrable <var>classname</var><DD>Particular service to
- * spawn/look for if the test needs and <code>Administrable</code>
- * service.
- *
- * <DT>-space <var>classname</var><DD>Particular type of JavaSpace
- * to spawn/look for if the test needs a <code>JavaSpace</code>.
- *
- * <DT>-waitAtEnd<DD> Wait for user input before exiting or killing services
- * under test
- *
- * <DT>-cleanupWait <var>long</var> </DT>
- * <DD> The number of milliseconds to wait after cleaning up (i.e.
- *      destroying the services) at the end of a test run.
- *      Defaults to 0.
- * </DD>
- *
- * </DL>
- *
- * Note: the "Sub" command line options (ie
- * <code>-administrableSub</code>, <code>-spaceSub</code> have
- * slightly different constraints depending on whether
- * <code>-external</code> is being used or not.  In stand alone mode
- * the test needs a concrete class that it can spawn.  In external
- * mode these option only need be specified so the test can uniquely
- * identify the service to test.  Thus if the only service the test
- * needed was a <code>JavaSpace</code>, and the designated lookup
- * service had only two registrants, the lookup service itself and a
- * JavaSpace, no command line argument would be necessary.  If the
- * test needed an <code>Administrable</code> the
- * <code>-administrableSub</code> command line argument would have to
- * be used to let the test know if it should be testing the lookup
- * service or the JavaSpace.
- */
-public abstract class TestBase extends QATestEnvironment {
-    volatile DiscoveryAdmin admin = null;
-
-    /**
-     * Holds instances to LRS proxy objects returned from StartService.
-     */
-    private final ArrayList startedServices = new ArrayList();//access using synchronized
-
-    /** URL to find lookup, null if we are in standAlone mode */
-    protected volatile LookupLocator locator = null;
-
-    /** Lookup groups to find lookup, null if we are in standAlone mode */
-    protected volatile String groups[] = null;
-
-    /**
-     * Number of milliseconds to wait after cleaning up the services.
-     */
-    protected volatile long cleanupWait = 0;
-
-    /** True is we are in standalone mode */
-    protected volatile boolean standAlone;
-
-    /**
-     * Flag that indicates we should try to scrub the services once we find them
-     */
-    protected volatile boolean scrub = false;
-
-    /** Flag that indicates we should not destroy on exit. */
-    protected volatile boolean destroy = true;
-
-    /**
-     * Class name to substitute for Administrable when looking/starting
-     * services to test
-     */
-    protected volatile String administrableSubstitute = null;
-
-    /**
-     * Class name to substitute for JavaSpace when looking/starting
-     * services to test
-     */
-    protected volatile String javaSpaceSubstitute = null;
-
-    /** List of leases to cancel during cleanup */
-    private final List leaseList = new java.util.LinkedList();//access using synchronized
-
-    /**
-     * Set of services to test.  @see#specifyServices for details
-     * 
-     * Only updated while holding lock to startedServices.
-     */
-    protected volatile Object[] services;
-
-    /**
-     * True if we should be using lookup
-     */
-    private volatile boolean useLookup;
-
-    /**
-     * If we kill a VM during the test the min time to wait before restart
-     */
-    protected volatile long minPostKillWait;
-
-    // Do we wait at the end
-    protected volatile boolean waitAtEnd;
-
-    /**
-     * the name of service for which these test are written
-     */
-    protected final String serviceName = "net.jini.lease.LeaseRenewalService";
-
-    public Test construct(QAConfig config) throws Exception {
-        super.construct(config);
-
-        // output the name of this test
-        logger.log(Level.FINE, "Test Name = " + this.getClass().getName());
-
-        // set security manager
-        System.setSecurityManager(new CombinerSecurityManager());
-        return new Test(){
-
-            public void run() throws Exception {
-                // do nothing
-            }
-            
-        };
-    }
-
-    protected void specifyServices(Class[] serviceClasses)
-            throws TestException {
-        try {
-            final String serviceClassNames[] = substitute(serviceClasses);
-            this.dbgSpecSrvcs(serviceClasses, serviceClassNames);
-
-            if (useLookup) {
-                ServiceRegistrar lookupProxy =
-		    getManager().startLookupService(); // prepared by util
-		// prepared by DiscoveryAdminUtil
-                admin = DiscoveryAdminUtil.getDiscoveryAdmin(lookupProxy);
-            }
-
-            // Setup services
-            synchronized (startedServices){
-                for (int i = 0; i < serviceClasses.length; i++) {
-                    logger.log(Level.FINE, "Starting service #" + i + ": "
-                            + serviceClassNames[i]);
-                    startedServices.add(getManager().startService(serviceClassNames[i]));
-                }
-                services = startedServices.toArray(new Object[startedServices.size()]);
-            }
-            if (scrub) {
-                for (int i = 0; i < services.length; i++) {
-                    if (services[i] instanceof JavaSpace) {
-                        scrubSpace((JavaSpace) services[i]);
-                    }
-                }
-            }
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            throw new TestException("Exception has been caught in"
-                    + " specifyServices: " + ex.getMessage());
-        }
-    }
-
-    private String[] substitute(Class[] source) {
-        String[] rslt = new String[source.length];
-
-        for (int i = 0; i < source.length; i++) {
-            if (source[i] == Administrable.class
-                    && administrableSubstitute != null) {
-                rslt[i] = administrableSubstitute;
-            } else if (source[i] == JavaSpace.class
-                    && javaSpaceSubstitute != null) {
-                rslt[i] = javaSpaceSubstitute;
-            } else {
-                rslt[i] = source[i].getName();
-            }
-        }
-        return rslt;
-    }
-    private static final int BLOCKING_FACTOR = 10;
-
-    protected void scrubSpace(JavaSpace space) throws TestException {
-        try {
-            JavaSpaceAdmin admin = (JavaSpaceAdmin) ((Administrable)
-                space).getAdmin();
-	    admin = (JavaSpaceAdmin) 
-		    getConfig().prepare("test.outriggerAdminPreparer",
-					admin);
-            final AdminIterator i = admin.contents(null, null, BLOCKING_FACTOR);
-
-            while (i.next() != null) {
-                i.delete();
-            }
-            i.close();
-        } catch (Exception e) {
-            throw new TestException(e.getMessage(),e);
-        }
-    }
-    private void dbgSpecSrvcs(Class[] serviceClasses,
-            String[] serviceClassNames) {
-        try {
-
-            // What classes
-            StringBuffer b = new StringBuffer("TestBase.specifyServices({");
-
-            if (serviceClasses != null) {
-                int i;
-
-                for (i = 0; i < serviceClasses.length; i++) {
-                    if (i > 0) {
-                        b.append(",");
-                    }
-
-                    if (serviceClassNames[i] != null) {
-                        b.append(serviceClassNames[i]);
-                    }
-                    String n = serviceClasses[i].getName();
-
-                    if (!n.equals(serviceClassNames[i])) {
-                        b.append("=");
-                        b.append(n);
-                    }
-                }
-            }
-            b.append("})");
-            logger.log(Level.FINE, b.toString());
-
-            // Which parameters?
-            logger.log(Level.FINE, "specifyServices groups=" + (this.groups == null ?
-                    "null" :
-                    java.util.Arrays.asList(this.groups).toString())
-                    + " locator=" + this.locator + " useLookup ="
-                    + this.useLookup);
-        } catch (Throwable uhoh) {
-
-            // don't kick the bucket just because the debug code is undebugged
-            logger.log(Level.FINE, "TestBase.dbgSpecSrvcs threw:");
-            uhoh.printStackTrace();
-        }
-    }
-
-    private long shutdownNoSleep(int index) throws Exception {
-        Object o = services[index];
-        try {
-	    if (!getManager().killVM(o)) {
-		logger.log(Level.SEVERE, "Could not call killVM for service " + o);
-            } else {
-		// get delay in seconds
-		int killDelay = 
-		    getConfig().getIntConfigVal("com.sun.jini.qa.harness.killvm.delay", 0);
-		if (killDelay > 0) {
-		    try {
-			Thread.sleep(killDelay * 1000);
-		    } catch (InterruptedException ignore) {
-		    }
-		}
-	    }
-	    return minPostKillWait; //XXX do I need to support the suggested wait time?
-        } catch (ClassCastException e) {
-            throw new UnsupportedOperationException("Don't know how to shutdown"
-                    + " a " + o.getClass().getName());
-        }
-    }
-
-    /**
-     * Attempts to shutdown the designated service.  Throws
-     * UnsupportedOperationException if it does not know how to
-     * shutdown the designated service.  Sleep for the time suggested
-     * by the service or by what is indicated by the restart_wait command line
-     * arg, which ever is greater.
-     */
-    protected void shutdown(int index) throws Exception {
-        Object o = services[index];
-
-        try {
-            final long suggestedWait = shutdownNoSleep(index);
-            final long willWait = Math.max(minPostKillWait, suggestedWait);
-            logger.log(Level.INFO, "Shutdown worked, sleeping for " + willWait
-                + " milliseconds...");
-            Thread.sleep(willWait);
-            logger.log(Level.INFO, "...awake");
-        } catch (InterruptedException e) {}
-    }
-
-    /**
-     * Attempts to shutdown the designated service.  Throws
-     * UnsupportedOperationException if it does not know how to
-     * shutdown the designated service.  Sleep for time indicated by the
-     * the second argument.  If the second argument is less than the time
-     * suggested by the service throws an IllegalArgumentException
-     */
-    protected void shutdown(int index, long wait) throws Exception {
-        Object o = services[index];
-
-        try {
-            final long suggestedWait = shutdownNoSleep(index);
-
-            if (suggestedWait > wait) {
-                throw new IllegalArgumentException("shutdown():Wait is "
-                        + "less than wait suggested by service");
-            }
-            logger.log(Level.INFO, "Shutdown worked, sleeping for " + wait
-                    + " milliseconds...");
-            Thread.sleep(wait);
-            logger.log(Level.INFO, "awake");
-        } catch (InterruptedException e) {}
-    }
-
-    /**
-     * TestBase keeps a list of leases that should be canceled in the
-     * cleanup phase, this method adds a lease to that list.  Note the
-     * leases on this list are not canceled if <code>TestBase</code>
-     * thinks the these resouces are going to be cleaned up someother
-     * way.
-     *
-     * @param lease     The Lease to be canceled
-     * @param unknownOk If <code>true</code>
-     *                  <code>UnknownLeaseException</code> will be
-     *                  ignored when this lease is cancled.
-     */
-    public void addLease(Lease lease, boolean unknownOk) {
-
-        // If we are just going to destroy all of the services, don't bother.
-        if (standAlone) {
-            return;
-        }
-        synchronized (leaseList) {
-            leaseList.add(new LeaseRec(lease, unknownOk));
-        }
-    }
-
-    
-    /**
-     * TestBase keeps a list of leases that should be canceled in the
-     * cleanup phase, this method adds a lease to that list. Before
-     * adding the lease, it is prepared using the <code>ProxyPreparer</code>
-     * named <code>test.outriggerLeasePreparer</code>. Note the
-     * leases on this list are not canceled if <code>TestBase</code>
-     * thinks the these resouces are going to be cleaned up someother
-     * way.
-     *
-     * @param lease     The Lease to be canceled
-     * @param unknownOk If <code>true</code>
-     *                  <code>UnknownLeaseException</code> will be
-     *                  ignored when this lease is cancled.
-     */
-    public void addOutriggerLease(Lease lease, boolean unknownOk) 
-	throws TestException 
-    {
-	ProxyPreparer p = null;
-	Configuration c = getConfig().getConfiguration();
-	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
-	    try {
-		p = (ProxyPreparer) c.getEntry("test",
-					       "outriggerLeasePreparer",
-					       ProxyPreparer.class);
-		lease = (Lease) p.prepareProxy(lease);
-	    } catch (ConfigurationException e) {
-		throw new TestException("Configuration error", e);
-	    } catch (RemoteException e) {
-		throw new TestException("RemoteException preparing lease",e);
-	    }
-	}
-	addLease(lease, unknownOk);
-    }
-
-    /**
-     * TestBase keeps a list of leases that should be canceled in the
-     * cleanup phase, this method adds a lease to that list. Before
-     * adding the lease, it is prepared using the <code>ProxyPreparer</code>
-     * named <code>test.outriggerLeasePreparer</code>. Note the
-     * leases on this list are not canceled if <code>TestBase</code>
-     * thinks the these resouces are going to be cleaned up someother
-     * way.
-     *
-     * @param lease     The Lease to be canceled
-     * @param unknownOk If <code>true</code>
-     *                  <code>UnknownLeaseException</code> will be
-     *                  ignored when this lease is cancled.
-     */
-    public void addMahaloLease(Lease lease, boolean unknownOk) 
-	throws TestException 
-    {
-	ProxyPreparer p = null;
-	Configuration c = getConfig().getConfiguration();
-	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
-	    try {
-		p = (ProxyPreparer) c.getEntry("test",
-					       "mahaloLeasePreparer",
-					       ProxyPreparer.class);
-		lease = (Lease) p.prepareProxy(lease);
-	    } catch (ConfigurationException e) {
-		throw new TestException("Configuration error", e);
-	    } catch (RemoteException e) {
-		throw new TestException("RemoteException preparing lease",e);
-	    }
-	}
-	addLease(lease, unknownOk);
-    }
-
-    private class LeaseRec {
-        final private Lease lease;
-        final private boolean unknownOk;
-
-        LeaseRec(Lease lease, boolean unknownOk) {
-            this.lease = lease;
-            this.unknownOk = unknownOk;
-        }
-
-        private void cancel() throws TestException {
-            try {
-                lease.cancel();
-            } catch (UnknownLeaseException e) {
-                if (!unknownOk) {
-                    cleanupFailure("UnknownLeaseException canceling lease:"
-                            + e.getMessage());
-                }
-            } catch (NoSuchObjectException ex) {
-
-                /*
-                 * Ignore it: it means that activatable object no longer
-                 * registered
-                 */
-            } catch (Throwable e) {
-                cleanupFailure("Could not cancel lease:" + e.getMessage());
-            }
-        }
-    }
-
-    /**
-     * Indicates cleanup failed, should only be called in the context
-     * of cleanup.  This method may return.
-     */
-    protected void cleanupFailure(String msg) throws TestException {
-        throw new TestException(msg);
-    }
-
-    protected void cleanupFailure(String msg, Throwable t) throws TestException {
-        throw new TestException(msg,t);
-    }
-
-    protected void setupFailure(String msg) throws TestException {
-        throw new TestException(msg);
-    }
-
-    protected void setupFailure(String msg, Throwable t) throws TestException {
-        throw new TestException(msg,t);
-    }
-
-
-
-    /**
-     * Called to tell the class that the specified service has been
-     * destroyed.  This will set its entry in the services array to null
-     */
-    protected void serviceDestroyed(int index) {
-        synchronized (startedServices){ //to avoid interleved write.
-            Object [] serv = services;
-            serv[index] = null;
-            services = serv; //guarantees change to volatile array is visible to other threads.
-        }
-    }
-
-    protected void parse() throws Exception {
-        javaSpaceSubstitute = getConfig().getStringConfigVal("com.sun.jini.test.share."
-                + "space", null);
-        scrub = getConfig().getBooleanConfigVal("com.sun.jini.test.share.scrub", false);
-        destroy = !getConfig().getBooleanConfigVal("com.sun.jini.test.share.noDestroy",
-                false);
-        administrableSubstitute = 
-	    getConfig().getStringConfigVal("com.sun.jini.test."
-                + "share.administrable", null);
-        useLookup = getConfig().getBooleanConfigVal("com.sun.jini.test.share.lookup",
-                true);
-        minPostKillWait = getConfig().getLongConfigVal("com.sun.jini.test.share."
-                + "restart_wait", 1000);
-        waitAtEnd = getConfig().getBooleanConfigVal("com.sun.jini.test.share.waitAtEnd",
-                false);
-        cleanupWait = getConfig().getLongConfigVal("com.sun.jini.test.share.cleanupWait",
-                0);
-
-        if (cleanupWait < 0) {
-            cleanupWait = 0;
-        }
-    }
-
-    /**
-     * Performs cleanup actions necessary to achieve a graceful exit of
-     * the current QA test.
-     * @exception TestException will usually indicate an "unresolved"
-     * condition because at this point the test has completed.
-     */
-    public void tearDown() {
-        try {
-//              for (int i = 0; i < services.length; i++) {
-//                  if (services[i] != null) {
-//                      try {
-//                          Administrable service = (Administrable) services[i];
-//                          DestroyAdmin dadmin = (DestroyAdmin) service.getAdmin();
-//                          dadmin.destroy();
-//                      } catch (NoSuchObjectException ex) {
-
-//                          /*
-//                           * Ignore it: it means that activatable object
-//                           * no longer registered
-//                           */
-//                      } catch (Throwable t) {
-//                          cleanupFailure("Trouble destroying " + services[i] +
-//                              " " + t.getMessage());
-//                      }
-//                  }
-//              }
-
-//              if (admin != null) {
-//                  try {
-//                      DestroyAdmin dadmin = (DestroyAdmin) admin;
-//                      dadmin.destroy();
-//                  } catch (Throwable t) {
-//                      cleanupFailure("Trouble destroying " + admin + " " +
-//                          t.getMessage());
-//                  }
-//              }
-
-            if (destroy) {
-                synchronized (leaseList) {
-                    for (Iterator i = leaseList.iterator(); i.hasNext();) {
-                        ((LeaseRec) i.next()).cancel();
-                    }
-                }
-
-                try {
-                    logger.log(Level.FINE, "Waiting " + cleanupWait
-                            + " ms after cleanup() call");
-
-                    if (cleanupWait > 0) {
-                        Thread.sleep(cleanupWait);
-                    }
-                } catch (InterruptedException e) {
-
-                    // Do nothing.
-                }
-            }
-        } catch (Exception ex) {
-            String message = "Warning: Test TestBase did not shutdown "
-                    + "cleanly!\n" + "Reason: " + ex.getMessage();
-            logger.log(Level.INFO, message);
-            ex.printStackTrace();
-        }
-	super.tearDown();
-    }
-
-    /**
-     * Assert that <code>entry</code> equals <code>other</code>.  Equivalent
-     * to <code>assertEquals(entry, other, desc, true)</code>
-     */
-    public void assertEquals(Entry entry, Entry other, String desc)
-            throws TestException {
-        assertEquals(entry, other, desc, true);
-    }
-
-    /**
-     * Assert that <code>entry</code> equals <code>other</code>, if
-     * <code>shouldBe</code> is <code>true</code>, or that it isn't, if
-     * <code>shouldBe</code> is <code>false</code>.
-     */
-    public void assertEquals(Entry entry, Entry other, String desc,
-            boolean shouldBe) throws TestException {
-        boolean matches;
-
-        if (entry == null || other == null) {
-            matches = (entry == null && other == null);
-        } else {
-            matches = entry.equals(other);
-        }
-
-        // otherwise use equals()
-        if (matches != shouldBe) {
-            new Throwable().printStackTrace();
-            String failOp = (shouldBe ? "!=" : "==");
-            throw new TestException(desc + " " + failOp + " original: ["
-                    + other + "] " + failOp + " [" + entry + "]");
-        }
-    }
-
-    /**
-     * Fail the tests writing <code>msg</code> in the log and
-     * including it in the fail message.  If <code>t</code> is non
-     * null its stack trace will also be dumped to the log.
-     */
-    synchronized protected void fail(String msg, Throwable t)
-            throws TestException {
-        logger.log(Level.FINE, msg);
-
-        if (t != null) {
-            t.printStackTrace();
-        }
-        throw new TestException(msg, t);
-    }
-
-    /**
-     * Fail the tests writing <code>msg</code> in the log and
-     * including it in the fail message.
-     */
-    protected void fail(String msg) throws TestException {
-        fail(msg, null);
-    }
-
-    protected LeaseRenewalSet prepareSet(LeaseRenewalSet set) 
-        throws TestException
-    {
-	Object s = getConfig().prepare("test.normRenewalSetPreparer", set);
-	return (LeaseRenewalSet) s;
-    }
-
-    protected EventRegistration prepareNormEventRegistration(EventRegistration reg) 
-        throws TestException
-    {
-	Object r = getConfig().prepare("test.normEventRegistrationPreparer", reg);
-	return (EventRegistration) r;
-    }
-
-    protected Lease prepareNormLease(Lease lease) throws TestException {
-	Object l = getConfig().prepare("test.normLeasePreparer", lease);
-	return (Lease) l;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.test.share;
+
+
+// java.*
+import java.rmi.NoSuchObjectException;
+import java.rmi.RemoteException;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+// net.jini
+import net.jini.core.discovery.LookupLocator;
+import net.jini.core.lease.Lease;
+import net.jini.core.entry.Entry;
+import net.jini.core.event.EventRegistration;
+import net.jini.core.lease.UnknownLeaseException;
+import net.jini.core.lookup.ServiceRegistrar;
+import net.jini.lease.LeaseRenewalSet;
+import net.jini.space.JavaSpace;
+import net.jini.admin.Administrable;
+import net.jini.lookup.DiscoveryAdmin;
+
+// com.sun.jini
+import com.sun.jini.outrigger.JavaSpaceAdmin;
+import com.sun.jini.outrigger.AdminIterator;
+
+
+// com.sun.jini.qa
+import com.sun.jini.qa.harness.QATestEnvironment;
+import com.sun.jini.qa.harness.TestException;
+import com.sun.jini.qa.harness.QAConfig;
+import com.sun.jini.qa.harness.Test;
+
+import java.util.logging.Level;
+
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationException;
+import net.jini.security.ProxyPreparer;
+import org.apache.river.api.security.CombinerSecurityManager;
+
+/**
+ * Base class for spaces QA tests.  Provides convenience functions for
+ * logging failure, starting/finding and cleaning up the services under
+ * test.  Also sets up a command line parser.
+ * <p>
+ * Tests provide an implementation of <code>runTest()</code> that
+ * performs the appropriate tests, using
+ * <code>specifyServices()</code> to indicate what services they need
+ * for the test.  Test failure should be indicated by calling
+ * <code>fail()</code> (or its close relative,
+ * <code>setupFailure()</code>) Passing can be indicated by calling
+ * <code>pass()</code> or by returning from <code>runTest()</code>
+ * normally. Tests should not invoke <code>Status.exit()</code>
+ * directly.
+ * <p>
+ * If a test needs to parse command line arguments it should override
+ * <code>parse()</code> and use the <code>CmdLine</code> command line
+ * parser provided in <code>line</code>.
+ * <p>
+ * If a test has to perform any post test cleanup it should override
+ * <code>cleanup()</code>
+ *
+ * Command line arguments
+ * <p>
+ * <DL>
+ * <DT>-external <var>jini-url</var><DD> The test will find the
+ * necessary services though the designated lookup service. Normally
+ * the test will start any necessary services with the exception of an
+ * activation demon.
+ *
+ * <DT>-scrub<DD> Can be used with <code>-external</code>. The test
+ * will attempt to put the services in a "clean" state before running
+ * the test.  Note this is currently implemented only for JavaSpaces.
+ *
+ * <DT>-administrable <var>classname</var><DD>Particular service to
+ * spawn/look for if the test needs and <code>Administrable</code>
+ * service.
+ *
+ * <DT>-space <var>classname</var><DD>Particular type of JavaSpace
+ * to spawn/look for if the test needs a <code>JavaSpace</code>.
+ *
+ * <DT>-waitAtEnd<DD> Wait for user input before exiting or killing services
+ * under test
+ *
+ * <DT>-cleanupWait <var>long</var> </DT>
+ * <DD> The number of milliseconds to wait after cleaning up (i.e.
+ *      destroying the services) at the end of a test run.
+ *      Defaults to 0.
+ * </DD>
+ *
+ * </DL>
+ *
+ * Note: the "Sub" command line options (ie
+ * <code>-administrableSub</code>, <code>-spaceSub</code> have
+ * slightly different constraints depending on whether
+ * <code>-external</code> is being used or not.  In stand alone mode
+ * the test needs a concrete class that it can spawn.  In external
+ * mode these option only need be specified so the test can uniquely
+ * identify the service to test.  Thus if the only service the test
+ * needed was a <code>JavaSpace</code>, and the designated lookup
+ * service had only two registrants, the lookup service itself and a
+ * JavaSpace, no command line argument would be necessary.  If the
+ * test needed an <code>Administrable</code> the
+ * <code>-administrableSub</code> command line argument would have to
+ * be used to let the test know if it should be testing the lookup
+ * service or the JavaSpace.
+ */
+public abstract class TestBase extends QATestEnvironment {
+    volatile DiscoveryAdmin admin = null;
+
+    /**
+     * Holds instances to LRS proxy objects returned from StartService.
+     */
+    private final ArrayList startedServices = new ArrayList();//access using synchronized
+
+    /** URL to find lookup, null if we are in standAlone mode */
+    protected volatile LookupLocator locator = null;
+
+    /** Lookup groups to find lookup, null if we are in standAlone mode */
+    protected volatile String groups[] = null;
+
+    /**
+     * Number of milliseconds to wait after cleaning up the services.
+     */
+    protected volatile long cleanupWait = 0;
+
+    /** True is we are in standalone mode */
+    protected volatile boolean standAlone;
+
+    /**
+     * Flag that indicates we should try to scrub the services once we find them
+     */
+    protected volatile boolean scrub = false;
+
+    /** Flag that indicates we should not destroy on exit. */
+    protected volatile boolean destroy = true;
+
+    /**
+     * Class name to substitute for Administrable when looking/starting
+     * services to test
+     */
+    protected volatile String administrableSubstitute = null;
+
+    /**
+     * Class name to substitute for JavaSpace when looking/starting
+     * services to test
+     */
+    protected volatile String javaSpaceSubstitute = null;
+
+    /** List of leases to cancel during cleanup */
+    private final List leaseList = new java.util.LinkedList();//access using synchronized
+
+    /**
+     * Set of services to test.  @see#specifyServices for details
+     * 
+     * Only updated while holding lock to startedServices.
+     */
+    protected volatile Object[] services;
+
+    /**
+     * True if we should be using lookup
+     */
+    private volatile boolean useLookup;
+
+    /**
+     * If we kill a VM during the test the min time to wait before restart
+     */
+    protected volatile long minPostKillWait;
+
+    // Do we wait at the end
+    protected volatile boolean waitAtEnd;
+
+    /**
+     * the name of service for which these test are written
+     */
+    protected final String serviceName = "net.jini.lease.LeaseRenewalService";
+
+    public Test construct(QAConfig config) throws Exception {
+        super.construct(config);
+
+        // output the name of this test
+        logger.log(Level.FINE, "Test Name = " + this.getClass().getName());
+
+        // set security manager
+        if (System.getSecurityManager() == null) {
+        System.setSecurityManager(new CombinerSecurityManager());
+        }
+        return new Test(){
+
+            public void run() throws Exception {
+                // do nothing
+            }
+            
+        };
+    }
+
+    protected void specifyServices(Class[] serviceClasses)
+            throws TestException {
+        try {
+            final String serviceClassNames[] = substitute(serviceClasses);
+            this.dbgSpecSrvcs(serviceClasses, serviceClassNames);
+
+            if (useLookup) {
+                ServiceRegistrar lookupProxy =
+		    getManager().startLookupService(); // prepared by util
+		// prepared by DiscoveryAdminUtil
+                admin = DiscoveryAdminUtil.getDiscoveryAdmin(lookupProxy);
+            }
+
+            // Setup services
+            synchronized (startedServices){
+                for (int i = 0; i < serviceClasses.length; i++) {
+                    logger.log(Level.FINE, "Starting service #" + i + ": "
+                            + serviceClassNames[i]);
+                    startedServices.add(getManager().startService(serviceClassNames[i]));
+                }
+                services = startedServices.toArray(new Object[startedServices.size()]);
+            }
+            if (scrub) {
+                for (int i = 0; i < services.length; i++) {
+                    if (services[i] instanceof JavaSpace) {
+                        scrubSpace((JavaSpace) services[i]);
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw new TestException("Exception has been caught in"
+                    + " specifyServices: " + ex.getMessage());
+        }
+    }
+
+    private String[] substitute(Class[] source) {
+        String[] rslt = new String[source.length];
+
+        for (int i = 0; i < source.length; i++) {
+            if (source[i] == Administrable.class
+                    && administrableSubstitute != null) {
+                rslt[i] = administrableSubstitute;
+            } else if (source[i] == JavaSpace.class
+                    && javaSpaceSubstitute != null) {
+                rslt[i] = javaSpaceSubstitute;
+            } else {
+                rslt[i] = source[i].getName();
+            }
+        }
+        return rslt;
+    }
+    private static final int BLOCKING_FACTOR = 10;
+
+    protected void scrubSpace(JavaSpace space) throws TestException {
+        try {
+            JavaSpaceAdmin admin = (JavaSpaceAdmin) ((Administrable)
+                space).getAdmin();
+	    admin = (JavaSpaceAdmin) 
+		    getConfig().prepare("test.outriggerAdminPreparer",
+					admin);
+            final AdminIterator i = admin.contents(null, null, BLOCKING_FACTOR);
+
+            while (i.next() != null) {
+                i.delete();
+            }
+            i.close();
+        } catch (Exception e) {
+            throw new TestException(e.getMessage(),e);
+        }
+    }
+    private void dbgSpecSrvcs(Class[] serviceClasses,
+            String[] serviceClassNames) {
+        try {
+
+            // What classes
+            StringBuffer b = new StringBuffer("TestBase.specifyServices({");
+
+            if (serviceClasses != null) {
+                int i;
+
+                for (i = 0; i < serviceClasses.length; i++) {
+                    if (i > 0) {
+                        b.append(",");
+                    }
+
+                    if (serviceClassNames[i] != null) {
+                        b.append(serviceClassNames[i]);
+                    }
+                    String n = serviceClasses[i].getName();
+
+                    if (!n.equals(serviceClassNames[i])) {
+                        b.append("=");
+                        b.append(n);
+                    }
+                }
+            }
+            b.append("})");
+            logger.log(Level.FINE, b.toString());
+
+            // Which parameters?
+            logger.log(Level.FINE, "specifyServices groups=" + (this.groups == null ?
+                    "null" :
+                    java.util.Arrays.asList(this.groups).toString())
+                    + " locator=" + this.locator + " useLookup ="
+                    + this.useLookup);
+        } catch (Throwable uhoh) {
+
+            // don't kick the bucket just because the debug code is undebugged
+            logger.log(Level.FINE, "TestBase.dbgSpecSrvcs threw:");
+            uhoh.printStackTrace();
+        }
+    }
+
+    private long shutdownNoSleep(int index) throws Exception {
+        Object o = services[index];
+        try {
+	    if (!getManager().killVM(o)) {
+		logger.log(Level.SEVERE, "Could not call killVM for service " + o);
+            } else {
+		// get delay in seconds
+		int killDelay = 
+		    getConfig().getIntConfigVal("com.sun.jini.qa.harness.killvm.delay", 0);
+		if (killDelay > 0) {
+		    try {
+			Thread.sleep(killDelay * 1000);
+		    } catch (InterruptedException ignore) {
+                        Thread.currentThread().interrupt();
+		    }
+		}
+	    }
+	    return minPostKillWait; //XXX do I need to support the suggested wait time?
+        } catch (ClassCastException e) {
+            throw new UnsupportedOperationException("Don't know how to shutdown"
+                    + " a " + o.getClass().getName());
+        }
+    }
+
+    /**
+     * Attempts to shutdown the designated service.  Throws
+     * UnsupportedOperationException if it does not know how to
+     * shutdown the designated service.  Sleep for the time suggested
+     * by the service or by what is indicated by the restart_wait command line
+     * arg, which ever is greater.
+     */
+    protected void shutdown(int index) throws Exception {
+        Object o = services[index];
+
+        try {
+            final long suggestedWait = shutdownNoSleep(index);
+            final long willWait = Math.max(minPostKillWait, suggestedWait);
+            logger.log(Level.INFO, "Shutdown worked, sleeping for " + willWait
+                + " milliseconds...");
+            Thread.sleep(willWait);
+            logger.log(Level.INFO, "...awake");
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+    }
+    }
+
+    /**
+     * Attempts to shutdown the designated service.  Throws
+     * UnsupportedOperationException if it does not know how to
+     * shutdown the designated service.  Sleep for time indicated by the
+     * the second argument.  If the second argument is less than the time
+     * suggested by the service throws an IllegalArgumentException
+     */
+    protected void shutdown(int index, long wait) throws Exception {
+        Object o = services[index];
+
+        try {
+            final long suggestedWait = shutdownNoSleep(index);
+
+            if (suggestedWait > wait) {
+                throw new IllegalArgumentException("shutdown():Wait is "
+                        + "less than wait suggested by service");
+            }
+            logger.log(Level.INFO, "Shutdown worked, sleeping for " + wait
+                    + " milliseconds...");
+            Thread.sleep(wait);
+            logger.log(Level.INFO, "awake");
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+    }
+    }
+
+    /**
+     * TestBase keeps a list of leases that should be canceled in the
+     * cleanup phase, this method adds a lease to that list.  Note the
+     * leases on this list are not canceled if <code>TestBase</code>
+     * thinks the these resouces are going to be cleaned up someother
+     * way.
+     *
+     * @param lease     The Lease to be canceled
+     * @param unknownOk If <code>true</code>
+     *                  <code>UnknownLeaseException</code> will be
+     *                  ignored when this lease is cancled.
+     */
+    public void addLease(Lease lease, boolean unknownOk) {
+
+        // If we are just going to destroy all of the services, don't bother.
+        if (standAlone) {
+            return;
+        }
+        synchronized (leaseList) {
+            leaseList.add(new LeaseRec(lease, unknownOk));
+        }
+    }
+
+    
+    /**
+     * TestBase keeps a list of leases that should be canceled in the
+     * cleanup phase, this method adds a lease to that list. Before
+     * adding the lease, it is prepared using the <code>ProxyPreparer</code>
+     * named <code>test.outriggerLeasePreparer</code>. Note the
+     * leases on this list are not canceled if <code>TestBase</code>
+     * thinks the these resouces are going to be cleaned up someother
+     * way.
+     *
+     * @param lease     The Lease to be canceled
+     * @param unknownOk If <code>true</code>
+     *                  <code>UnknownLeaseException</code> will be
+     *                  ignored when this lease is cancled.
+     */
+    public void addOutriggerLease(Lease lease, boolean unknownOk) 
+	throws TestException 
+    {
+	ProxyPreparer p = null;
+	Configuration c = getConfig().getConfiguration();
+	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
+	    try {
+		p = (ProxyPreparer) c.getEntry("test",
+					       "outriggerLeasePreparer",
+					       ProxyPreparer.class);
+		lease = (Lease) p.prepareProxy(lease);
+	    } catch (ConfigurationException e) {
+		throw new TestException("Configuration error", e);
+	    } catch (RemoteException e) {
+		throw new TestException("RemoteException preparing lease",e);
+	    }
+	}
+	addLease(lease, unknownOk);
+    }
+
+    /**
+     * TestBase keeps a list of leases that should be canceled in the
+     * cleanup phase, this method adds a lease to that list. Before
+     * adding the lease, it is prepared using the <code>ProxyPreparer</code>
+     * named <code>test.outriggerLeasePreparer</code>. Note the
+     * leases on this list are not canceled if <code>TestBase</code>
+     * thinks the these resouces are going to be cleaned up someother
+     * way.
+     *
+     * @param lease     The Lease to be canceled
+     * @param unknownOk If <code>true</code>
+     *                  <code>UnknownLeaseException</code> will be
+     *                  ignored when this lease is cancled.
+     */
+    public void addMahaloLease(Lease lease, boolean unknownOk) 
+	throws TestException 
+    {
+	ProxyPreparer p = null;
+	Configuration c = getConfig().getConfiguration();
+	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
+	    try {
+		p = (ProxyPreparer) c.getEntry("test",
+					       "mahaloLeasePreparer",
+					       ProxyPreparer.class);
+		lease = (Lease) p.prepareProxy(lease);
+	    } catch (ConfigurationException e) {
+		throw new TestException("Configuration error", e);
+	    } catch (RemoteException e) {
+		throw new TestException("RemoteException preparing lease",e);
+	    }
+	}
+	addLease(lease, unknownOk);
+    }
+
+    private class LeaseRec {
+        final private Lease lease;
+        final private boolean unknownOk;
+
+        LeaseRec(Lease lease, boolean unknownOk) {
+            this.lease = lease;
+            this.unknownOk = unknownOk;
+        }
+
+        private void cancel() throws TestException {
+            try {
+                lease.cancel();
+            } catch (UnknownLeaseException e) {
+                if (!unknownOk) {
+                    cleanupFailure("UnknownLeaseException canceling lease:"
+                            + e.getMessage());
+                }
+            } catch (NoSuchObjectException ex) {
+
+                /*
+                 * Ignore it: it means that activatable object no longer
+                 * registered
+                 */
+            } catch (Throwable e) {
+                cleanupFailure("Could not cancel lease:" + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Indicates cleanup failed, should only be called in the context
+     * of cleanup.  This method may return.
+     */
+    protected void cleanupFailure(String msg) throws TestException {
+        throw new TestException(msg);
+    }
+
+    protected void cleanupFailure(String msg, Throwable t) throws TestException {
+        throw new TestException(msg,t);
+    }
+
+    protected void setupFailure(String msg) throws TestException {
+        throw new TestException(msg);
+    }
+
+    protected void setupFailure(String msg, Throwable t) throws TestException {
+        throw new TestException(msg,t);
+    }
+
+
+
+    /**
+     * Called to tell the class that the specified service has been
+     * destroyed.  This will set its entry in the services array to null
+     */
+    protected void serviceDestroyed(int index) {
+        synchronized (startedServices){ //to avoid interleved write.
+            Object [] serv = services;
+            serv[index] = null;
+            services = serv; //guarantees change to volatile array is visible to other threads.
+        }
+    }
+
+    protected void parse() throws Exception {
+        javaSpaceSubstitute = getConfig().getStringConfigVal("com.sun.jini.test.share."
+                + "space", null);
+        scrub = getConfig().getBooleanConfigVal("com.sun.jini.test.share.scrub", false);
+        destroy = !getConfig().getBooleanConfigVal("com.sun.jini.test.share.noDestroy",
+                false);
+        administrableSubstitute = 
+	    getConfig().getStringConfigVal("com.sun.jini.test."
+                + "share.administrable", null);
+        useLookup = getConfig().getBooleanConfigVal("com.sun.jini.test.share.lookup",
+                true);
+        minPostKillWait = getConfig().getLongConfigVal("com.sun.jini.test.share."
+                + "restart_wait", 1000);
+        waitAtEnd = getConfig().getBooleanConfigVal("com.sun.jini.test.share.waitAtEnd",
+                false);
+        cleanupWait = getConfig().getLongConfigVal("com.sun.jini.test.share.cleanupWait",
+                0);
+
+        if (cleanupWait < 0) {
+            cleanupWait = 0;
+        }
+    }
+
+    /**
+     * Performs cleanup actions necessary to achieve a graceful exit of
+     * the current QA test.
+     * @exception TestException will usually indicate an "unresolved"
+     * condition because at this point the test has completed.
+     */
+    public void tearDown() {
+        try {
+//              for (int i = 0; i < services.length; i++) {
+//                  if (services[i] != null) {
+//                      try {
+//                          Administrable service = (Administrable) services[i];
+//                          DestroyAdmin dadmin = (DestroyAdmin) service.getAdmin();
+//                          dadmin.destroy();
+//                      } catch (NoSuchObjectException ex) {
+
+//                          /*
+//                           * Ignore it: it means that activatable object
+//                           * no longer registered
+//                           */
+//                      } catch (Throwable t) {
+//                          cleanupFailure("Trouble destroying " + services[i] +
+//                              " " + t.getMessage());
+//                      }
+//                  }
+//              }
+
+//              if (admin != null) {
+//                  try {
+//                      DestroyAdmin dadmin = (DestroyAdmin) admin;
+//                      dadmin.destroy();
+//                  } catch (Throwable t) {
+//                      cleanupFailure("Trouble destroying " + admin + " " +
+//                          t.getMessage());
+//                  }
+//              }
+
+            if (destroy) {
+                synchronized (leaseList) {
+                    for (Iterator i = leaseList.iterator(); i.hasNext();) {
+                        ((LeaseRec) i.next()).cancel();
+                    }
+                }
+
+                try {
+                    logger.log(Level.FINE, "Waiting " + cleanupWait
+                            + " ms after cleanup() call");
+
+                    if (cleanupWait > 0) {
+                        Thread.sleep(cleanupWait);
+                    }
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    // Do nothing.
+                }
+            }
+        } catch (Exception ex) {
+            String message = "Warning: Test TestBase did not shutdown "
+                    + "cleanly!\n" + "Reason: " + ex.getMessage();
+            logger.log(Level.INFO, message);
+            ex.printStackTrace();
+        }
+	super.tearDown();
+    }
+
+    /**
+     * Assert that <code>entry</code> equals <code>other</code>.  Equivalent
+     * to <code>assertEquals(entry, other, desc, true)</code>
+     */
+    public void assertEquals(Entry entry, Entry other, String desc)
+            throws TestException {
+        assertEquals(entry, other, desc, true);
+    }
+
+    /**
+     * Assert that <code>entry</code> equals <code>other</code>, if
+     * <code>shouldBe</code> is <code>true</code>, or that it isn't, if
+     * <code>shouldBe</code> is <code>false</code>.
+     */
+    public void assertEquals(Entry entry, Entry other, String desc,
+            boolean shouldBe) throws TestException {
+        boolean matches;
+
+        if (entry == null || other == null) {
+            matches = (entry == null && other == null);
+        } else {
+            matches = entry.equals(other);
+        }
+
+        // otherwise use equals()
+        if (matches != shouldBe) {
+            new Throwable().printStackTrace();
+            String failOp = (shouldBe ? "!=" : "==");
+            throw new TestException(desc + " " + failOp + " original: ["
+                    + other + "] " + failOp + " [" + entry + "]");
+        }
+    }
+
+    /**
+     * Fail the tests writing <code>msg</code> in the log and
+     * including it in the fail message.  If <code>t</code> is non
+     * null its stack trace will also be dumped to the log.
+     */
+    synchronized protected void fail(String msg, Throwable t)
+            throws TestException {
+        logger.log(Level.FINE, msg);
+
+        if (t != null) {
+            t.printStackTrace();
+        }
+        throw new TestException(msg, t);
+    }
+
+    /**
+     * Fail the tests writing <code>msg</code> in the log and
+     * including it in the fail message.
+     */
+    protected void fail(String msg) throws TestException {
+        fail(msg, null);
+    }
+
+    protected LeaseRenewalSet prepareSet(LeaseRenewalSet set) 
+        throws TestException
+    {
+	Object s = getConfig().prepare("test.normRenewalSetPreparer", set);
+	return (LeaseRenewalSet) s;
+    }
+
+    protected EventRegistration prepareNormEventRegistration(EventRegistration reg) 
+        throws TestException
+    {
+	Object r = getConfig().prepare("test.normEventRegistrationPreparer", reg);
+	return (EventRegistration) r;
+    }
+
+    protected Lease prepareNormLease(Lease lease) throws TestException {
+	Object l = getConfig().prepare("test.normLeasePreparer", lease);
+	return (Lease) l;
+    }
+}

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestParticipantImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestParticipantImpl.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestParticipantImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TestParticipantImpl.java Sun Oct 26 13:17:28 2014
@@ -211,7 +211,7 @@ public class TestParticipantImpl
 	try {
 	    Thread.sleep(millis);
 	} catch (InterruptedException ie) {
-	    ;
+            Thread.currentThread().interrupt();
 	}
     }
 

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TesterTransactionManager.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TesterTransactionManager.java?rev=1634322&r1=1634321&r2=1634322&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TesterTransactionManager.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/TesterTransactionManager.java Sun Oct 26 13:17:28 2014
@@ -1,235 +1,240 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.test.share;
-
-import java.util.logging.Level;
-
-// All imports
-import net.jini.core.transaction.*;
-import net.jini.core.transaction.server.*;
-import java.rmi.*;
-import java.rmi.server.*;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import java.util.logging.Logger;
-import java.util.logging.Level;
-
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.Subject;
-
-import net.jini.export.Exporter;
-import net.jini.config.Configuration;
-import net.jini.config.ConfigurationException;
-import net.jini.security.TrustVerifier;
-import net.jini.security.proxytrust.ProxyTrust;
-import com.sun.jini.qa.harness.QATestEnvironment;
-import com.sun.jini.qa.harness.QAConfig;
-
-/**
- * This class provides a simple transaction manager that tests can use
- * to test a particpant.  It is not designed to be robust in any way,
- * just to allow a test to drive the participant to various parts of
- * the transaction in a controlled way.  This means that some of the
- * methods are not supported -- anything not needed by a participant
- * may have a simpler local version, since this is always used locally
- * by the test.
- */
-public class TesterTransactionManager
-        implements TransactionManager, TransactionConstants, Serializable, ProxyTrust {
-
-    private static Logger logger = 
-	Logger.getLogger("com.sun.jini.qa.harness");
-
-    private static int serviceID = 100;
-
-    /** Our transaction objects. */
-    private Map txns = Collections.synchronizedMap(new HashMap());
-
-    /** The next ID to allocate. */
-    private static long nextID = 1;
-
-    LoginContext context;
-
-    private Object proxy;
-    private Object myRef;
-
-    public TesterTransactionManager() throws RemoteException {
-	Configuration c = QAConfig.getConfig().getConfiguration();
-	context = null;
-	try {
-	    context = (LoginContext) c.getEntry("test", 
-						"mahaloLoginContext",
-						LoginContext.class, 
-						null);
-	    if (context != null) {
-		logger.log(Level.FINEST, "got a TesterTransactionManager login context");
-	    }
-	} catch (Throwable e) {
-	    throw new RemoteException("Configuration error", e);
-	}	
-	if (context != null) {
-	    doExportWithLogin(context, c);
-	} else {
-	    doExport(c);
-	}
-    }
-
-    public TrustVerifier getProxyVerifier() {
-	return new TesterTransactionManagerProxyVerifier((TransactionManager) myRef);
-    }
-
-    private void doExport(Configuration c) throws RemoteException {
-	Exporter exporter = QAConfig.getDefaultExporter();
-	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
-	    try {
-		exporter = (Exporter) c.getEntry("test",
-						 "testerTransactionManagerExporter",
-						 Exporter.class);
-	    } catch (ConfigurationException e) {
-		throw new RemoteException("Configuration error", e);
-	    }
-	}
-	myRef = exporter.export(this);
-	proxy = TesterTransactionManagerProxy.getInstance(
-				 (TransactionManager) myRef, serviceID++);
-    }
-    
-    private void doExportWithLogin(LoginContext context, final Configuration c) 
-	throws RemoteException
-    {
-	try {
-	    context.login();
-	} catch (Throwable e) {
-	    throw new RemoteException("Login failed", e);
-	}
-	try {
-	    Subject.doAsPrivileged(context.getSubject(),
-				   new PrivilegedExceptionAction() {
-					   public Object run() throws RemoteException {
-					       doExport(c);
-					       return null;
-					   }
-				       },
-				   null);
-	} catch (PrivilegedActionException e) {
-	    Throwable t = e.getException();
-	    throw new RemoteException("doAs failed", t);
-	} catch (Throwable e) {
-	    throw new RemoteException("doAs failed", e);
-	}
-    }
-
-    public Object writeReplace() throws ObjectStreamException {
-	return proxy;
-    }
-
-    /**
-     * Return a new <code>ServerTransaction</code> object.
-     */
-    public TesterTransaction create() {
-        TesterTransaction tt = new TesterTransaction(this, nextID());
-        txns.put(tt.idObj, tt);
-        return tt;
-    }
-
-    /**
-     * Return the next transaction id.
-     */
-    private static synchronized long nextID() {
-        return nextID++;
-    }
-
-    /**
-     * This implementation ignores the time -- it is always synchronous.
-     */
-    public void commit(long id, long timeout)
-            throws UnknownTransactionException, CannotCommitException,
-            RemoteException {
-        commit(id);
-    }
-
-    /**
-     * This implementation ignores the time -- it is always synchronous.
-     */
-    public void commit(long id)
-            throws UnknownTransactionException, CannotCommitException,
-            RemoteException {
-        tt(id).commit();
-    }
-
-    private TesterTransaction tt(long id) throws UnknownTransactionException {
-        try {
-            return (TesterTransaction) txns.get(new Long(id));
-        } catch (NullPointerException e) {
-            throw new UnknownTransactionException("" + id);
-        }
-    }
-
-    /**
-     * This implementation ignores the time -- it is always synchronous.
-     */
-    public void abort(long id, long timeout)
-            throws UnknownTransactionException, CannotAbortException,
-            RemoteException {
-        abort(id);
-    }
-
-    /**
-     * This implementation ignores the time -- it is always synchronous.
-     */
-    public void abort(long id)
-            throws UnknownTransactionException, CannotAbortException,
-            RemoteException {
-        tt(id).sendAbort();
-    }
-
-    /**
-     * @throws UnsupportedOperationException
-     *            Use <code>create()</code>: no leases or other mess
-     *            supported or needed in this local case.
-     * @see #create()
-     */
-    public TransactionManager.Created create(long leaseTime) {
-        throw new UnsupportedOperationException("don't get fancy: use"
-                + " create()");
-    }
-
-    /**
-     * Return the current state of this transasction.
-     */
-    public int getState(long id)
-            throws UnknownTransactionException, RemoteException {
-        return tt(id).getState();
-    }
-
-    /**
-     * Join the transaction.  Only one participant in each transaction,
-     * currently.
-     */
-    public void join(long id, TransactionParticipant part, long crashCnt)
-            throws UnknownTransactionException, CannotJoinException,
-            CrashCountException {
-        tt(id).join(part, crashCnt);
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.test.share;
+
+import com.sun.jini.qa.harness.QAConfig;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationException;
+import net.jini.core.transaction.*;
+import net.jini.core.transaction.server.*;
+import net.jini.export.Exporter;
+import net.jini.security.TrustVerifier;
+import net.jini.security.proxytrust.ProxyTrust;
+import org.apache.river.api.util.Startable;
+
+/**
+ * This class provides a simple transaction manager that tests can use
+ * to test a particpant.  It is not designed to be robust in any way,
+ * just to allow a test to drive the participant to various parts of
+ * the transaction in a controlled way.  This means that some of the
+ * methods are not supported -- anything not needed by a participant
+ * may have a simpler local version, since this is always used locally
+ * by the test.
+ */
+public class TesterTransactionManager
+        implements TransactionManager, TransactionConstants, Serializable, ProxyTrust, Startable {
+
+    private static Logger logger = 
+	Logger.getLogger("com.sun.jini.qa.harness");
+
+    private static int serviceID = 100;
+
+    /** Our transaction objects. */
+    private final Map txns;
+
+    /** The next ID to allocate. */
+    private static long nextID = 1;
+
+    final LoginContext context;
+    final RemoteException exception;
+    final Configuration c;
+
+    private Object proxy;
+    private Object myRef;
+
+    public TesterTransactionManager() throws RemoteException {
+        this.txns = Collections.synchronizedMap(new HashMap());
+        c = QAConfig.getConfig().getConfiguration();
+	LoginContext context = null;
+        RemoteException exception = null;
+	try {
+	    context = (LoginContext) c.getEntry("test", 
+						"mahaloLoginContext",
+						LoginContext.class, 
+						null);
+	    if (context != null) {
+		logger.log(Level.FINEST, "got a TesterTransactionManager login context");
+	    }
+	} catch (Throwable e) {
+	    exception = new RemoteException("Configuration error", e);
+	} finally {
+            this.context = context;
+            this.exception = exception;
+	}	
+	}
+
+    public synchronized TrustVerifier getProxyVerifier() {
+	return new TesterTransactionManagerProxyVerifier((TransactionManager) myRef);
+    }
+
+    private void doExport(Configuration c) throws RemoteException {
+	Exporter exporter = QAConfig.getDefaultExporter();
+	if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
+	    try {
+		exporter = (Exporter) c.getEntry("test",
+						 "testerTransactionManagerExporter",
+						 Exporter.class);
+	    } catch (ConfigurationException e) {
+		throw new RemoteException("Configuration error", e);
+	    }
+	}
+	myRef = exporter.export(this);
+	proxy = TesterTransactionManagerProxy.getInstance(
+				 (TransactionManager) myRef, serviceID++);
+    }
+    
+    private void doExportWithLogin(LoginContext context, final Configuration c) 
+	throws RemoteException
+    {
+	try {
+	    context.login();
+	} catch (Throwable e) {
+	    throw new RemoteException("Login failed", e);
+	}
+	try {
+	    Subject.doAsPrivileged(context.getSubject(),
+				   new PrivilegedExceptionAction() {
+					   public Object run() throws RemoteException {
+					       doExport(c);
+					       return null;
+					   }
+				       },
+				   null);
+	} catch (PrivilegedActionException e) {
+	    Throwable t = e.getException();
+	    throw new RemoteException("doAs failed", t);
+	} catch (Throwable e) {
+	    throw new RemoteException("doAs failed", e);
+	}
+    }
+
+    public synchronized Object writeReplace() throws ObjectStreamException {
+	return proxy;
+    }
+
+    /**
+     * Return a new <code>ServerTransaction</code> object.
+     */
+    public synchronized TesterTransaction create() {
+        TesterTransaction tt = new TesterTransaction(this, nextID());
+        txns.put(tt.idObj, tt);
+        return tt;
+    }
+
+    /**
+     * Return the next transaction id.
+     */
+    private static synchronized long nextID() {
+        return nextID++;
+    }
+
+    /**
+     * This implementation ignores the time -- it is always synchronous.
+     */
+    public void commit(long id, long timeout)
+            throws UnknownTransactionException, CannotCommitException,
+            RemoteException {
+        commit(id);
+    }
+
+    /**
+     * This implementation ignores the time -- it is always synchronous.
+     */
+    public synchronized void commit(long id)
+            throws UnknownTransactionException, CannotCommitException,
+            RemoteException {
+        tt(id).commit();
+    }
+
+    private TesterTransaction tt(long id) throws UnknownTransactionException {
+        try {
+            return (TesterTransaction) txns.get(new Long(id));
+        } catch (NullPointerException e) {
+            throw new UnknownTransactionException("" + id);
+        }
+    }
+
+    /**
+     * This implementation ignores the time -- it is always synchronous.
+     */
+    public void abort(long id, long timeout)
+            throws UnknownTransactionException, CannotAbortException,
+            RemoteException {
+        abort(id);
+    }
+
+    /**
+     * This implementation ignores the time -- it is always synchronous.
+     */
+    public synchronized void abort(long id)
+            throws UnknownTransactionException, CannotAbortException,
+            RemoteException {
+        tt(id).sendAbort();
+    }
+
+    /**
+     * @throws UnsupportedOperationException
+     *            Use <code>create()</code>: no leases or other mess
+     *            supported or needed in this local case.
+     * @see #create()
+     */
+    public TransactionManager.Created create(long leaseTime) {
+        throw new UnsupportedOperationException("don't get fancy: use"
+                + " create()");
+    }
+
+    /**
+     * Return the current state of this transasction.
+     */
+    public synchronized int getState(long id)
+            throws UnknownTransactionException, RemoteException {
+        return tt(id).getState();
+    }
+
+    /**
+     * Join the transaction.  Only one participant in each transaction,
+     * currently.
+     */
+    public synchronized void join(long id, TransactionParticipant part, long crashCnt)
+            throws UnknownTransactionException, CannotJoinException,
+            CrashCountException {
+        tt(id).join(part, crashCnt);
+    }
+
+    @Override
+    public synchronized void start() throws Exception {
+        if (exception != null) throw exception;
+        if (context != null) {
+	    doExportWithLogin(context, c);
+	} else {
+	    doExport(c);
+}
+    }
+}



Mime
View raw message