Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QATestEnvironment.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QATestEnvironment.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QATestEnvironment.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/QATestEnvironment.java Sun Oct 26 13:17:28 2014 @@ -1,262 +1,264 @@ -/* - * 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.qa.harness; - -import java.io.IOException; -import java.io.FileWriter; -import java.io.PrintWriter; -import java.io.File; -import java.rmi.RemoteException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Logger; -import java.util.logging.Level; - -import net.jini.core.lease.Lease; -import net.jini.core.lease.UnknownLeaseException; - -/** - * A base class for tests to be run by the harness. - * It implements the <code>com.sun.jini.qa.harness.TestEnvironment</code> interface. - * Minimal implementations for <code>construct</code> and <code>teardown</code> - * are provided. Subclasses of this class are responsible for implementing - * the <code>com.sun.jini.qa.harness.Test</code> interface <code>run</code> method, and may override - * <code>construct</code> and <code>teardown</code> to add test specific - * initialization and cleanup operations. - * <p> - * A protected <code>logger</code> is instantiated by this class for use - * by subclasses, with the logger name <code>com.sun.jini.qa.harness.test</code>. - */ -public abstract class QATestEnvironment implements TestEnvironment { - - /** the logger */ - protected static final Logger logger = - Logger.getLogger("com.sun.jini.qa.harness"); - - /** Keeps track of leases for automatic cancellation when test ends. */ - private final Collection<Lease> leaseArray = new ArrayList<Lease>();//access must be synchronized - /** The admin manager for managing services */ - private volatile AdminManager manager; - - /** The config object for accessing the test environment */ - private volatile QAConfig config; - - /** - * Mostly mimics the behavior of the assert keyword. - * If <code>condition</code> is <code>true</code>, the method - * returns silently. If <code>condition</code> is <code>false</code>, - * the method throws <code>TestException</code> with the detail message - * of <code>failureMsg</code>. - * - * @param condition the condition to evaluate - * @param failureMsg the exception message to provide - * @throws TestException if <code>condition</code> is <code>false</code> - */ - public void assertion(boolean condition, String failureMsg) - throws TestException - { - if (!condition) throw new TestException(failureMsg); - } - - /** - * Mostly mimics the behavior of the assert keyword. - * If <code>condition</code> is <code>true</code>, the method - * returns silently. If <code>condition</code> is <code>false</code>, - * the method throws <code>TestException</code>. - * - * @param condition the condition to evaluate - * @throws TestException if <code>condition</code> is <code>false</code> - */ - public void assertion(boolean condition) - throws TestException - { - if (!condition) throw new TestException(); - } - - /** - * Return the <code>QAConfig</code> object for the test environment. - * - * @return the harness QAConfig <code>object</code> - */ - public QAConfig getConfig() { - return config; - } - - /** - * This method is called by the <code>MasterTest</code> immediately before - * the run method is called. Override this method to implement test specific - * construct code. This method: - * <ul> - * <li>saves a reference to <code>config</code> - * <li>starts the class server identified by the - * <code>serviceName</code> "qaClassServer" if the config value - * named <code>com.sun.jini.qa.harness.runkitserver</code> is - * <code>true</code> (the default) - * <li>starts the class server identified by the - * <code>serviceName</code> "jiniClassServer" if the config value - * named <code>com.sun.jini.qa.harness.runjiniserver</code> is - * <code>true</code> (the default) - * </ul> - * <P> - * In the majority of cases this method will be overridden. The first action - * taken by the method should be a call to - * <code>super.construct(sysConfig)</code>. - * - * @throws Exception if any failure occurs during construct - */ - public Test construct(QAConfig config) throws Exception { - int delayTime = - config.getIntConfigVal("com.sun.jini.qa.harness.startDelay", 0); - if (delayTime > 0) { - try { - Thread.sleep(1000 * delayTime); - } catch (InterruptedException ignore) { - } - } - this.config = config; - manager = new AdminManager(config); - if (config.getBooleanConfigVal("com.sun.jini.qa.harness.runkitserver", - true)) - { - getManager().startService("qaClassServer"); - SlaveRequest request = new StartClassServerRequest("qaClassServer"); - SlaveTest.broadcast(request); - } - if (config.getBooleanConfigVal("com.sun.jini.qa.harness.runjiniserver", - true)) - { - getManager().startService("jiniClassServer"); - SlaveRequest request = - new StartClassServerRequest("jiniClassServer"); - SlaveTest.broadcast(request); - } - String testClassServer = - config.getStringConfigVal("com.sun.jini.qa.harness.testClassServer", - ""); - if (testClassServer.trim().length() > 0) { - getManager().startService("testClassServer"); - SlaveRequest request = - new StartClassServerRequest(testClassServer); - SlaveTest.broadcast(request); - } - return new Test(){ - - public void run() throws Exception { - // Do nothing - } - - }; - } - - /** - * This method is called by the <code>MasterTest</code> immediately after - * the run method returns. Override this method to implement test specific - * cleanup code. This method cancels all tracked leases, destroys all - * services that were started by the <code>AdminManager</code>, and sends - * a <code>TeardownRequest</code> to all participating - * <code>SlaveTest</code>s. - * <p> - * If this method is overridden, the overriding method should include - * a call to <code>super.teardown()</code>. In most cases, this will - * be done as the final action of the overriding method, since test specific - * cleanup may depend on access to services destroyed by this method. - */ - public void tearDown() { - cancelTrackedLeases(); - if (getManager() != null) { // null if test didn't call super.construct - try { - logger.log(Level.FINE, - "Destroying remaining managed services"); - getManager().destroyAllServices(); - } catch (Exception ex) { - logger.log(Level.INFO, - "Unexpected exception while cleaning up services", - ex); - } - } - SlaveTest.broadcast(new TeardownRequest()); - } - - /** - * Track a lease for automatic cancellation when the test ends. - * - * @param lease the Lease to add to the tracking array - */ - public void trackLease(Lease lease) { - synchronized (leaseArray){ - leaseArray.add(lease); - } - } - - /** - * Cancel all Leases that have been tracked by the caller. - * <code>UnknownLeaseExceptions</code> are silently ignored. - * <code>RemoteExceptions</code> cause an error message to - * be written to the log. In all cases, all of the tracked - * leases are discarded. - */ - public void cancelTrackedLeases() { - // copy leaseArray to avoid calling remote method while synchronized. - Collection<Lease> cancel; - synchronized (leaseArray){ - cancel = new ArrayList<Lease>(leaseArray.size()); - cancel.addAll(leaseArray); - leaseArray.clear(); - } - Iterator<Lease> iter = cancel.iterator(); - while (iter.hasNext()) { - Lease lease = iter.next(); - try { - lease.cancel(); - } catch (UnknownLeaseException ignore) { - } catch (RemoteException ex) { - logger.log(Level.INFO, "Failed to cancel lease", ex); - } - } - } - - // delay is done here in case multiple groups are present - public void forceThreadDump() { - Iterator it = getManager().iterator(); - while (it.hasNext()) { - Object admin = it.next(); - if (admin instanceof NonActivatableGroupAdmin) { - if (((NonActivatableGroupAdmin) admin).forceThreadDump()) { - try { - Thread.sleep(5000); // give it time to flush - } catch (InterruptedException e) { - } - } - } - } - } - - /** - * @return the manager - */ - protected AdminManager getManager() { - return manager; - } - -} +/* + * 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.qa.harness; + +import java.io.IOException; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.io.File; +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Logger; +import java.util.logging.Level; + +import net.jini.core.lease.Lease; +import net.jini.core.lease.UnknownLeaseException; + +/** + * A base class for tests to be run by the harness. + * It implements the <code>com.sun.jini.qa.harness.TestEnvironment</code> interface. + * Minimal implementations for <code>construct</code> and <code>teardown</code> + * are provided. Subclasses of this class are responsible for implementing + * the <code>com.sun.jini.qa.harness.Test</code> interface <code>run</code> method, and may override + * <code>construct</code> and <code>teardown</code> to add test specific + * initialization and cleanup operations. + * <p> + * A protected <code>logger</code> is instantiated by this class for use + * by subclasses, with the logger name <code>com.sun.jini.qa.harness.test</code>. + */ +public abstract class QATestEnvironment implements TestEnvironment { + + /** the logger */ + protected static final Logger logger = + Logger.getLogger("com.sun.jini.qa.harness"); + + /** Keeps track of leases for automatic cancellation when test ends. */ + private final Collection<Lease> leaseArray = new ArrayList<Lease>();//access must be synchronized + /** The admin manager for managing services */ + private volatile AdminManager manager; + + /** The config object for accessing the test environment */ + private volatile QAConfig config; + + /** + * Mostly mimics the behavior of the assert keyword. + * If <code>condition</code> is <code>true</code>, the method + * returns silently. If <code>condition</code> is <code>false</code>, + * the method throws <code>TestException</code> with the detail message + * of <code>failureMsg</code>. + * + * @param condition the condition to evaluate + * @param failureMsg the exception message to provide + * @throws TestException if <code>condition</code> is <code>false</code> + */ + public void assertion(boolean condition, String failureMsg) + throws TestException + { + if (!condition) throw new TestException(failureMsg); + } + + /** + * Mostly mimics the behavior of the assert keyword. + * If <code>condition</code> is <code>true</code>, the method + * returns silently. If <code>condition</code> is <code>false</code>, + * the method throws <code>TestException</code>. + * + * @param condition the condition to evaluate + * @throws TestException if <code>condition</code> is <code>false</code> + */ + public void assertion(boolean condition) + throws TestException + { + if (!condition) throw new TestException(); + } + + /** + * Return the <code>QAConfig</code> object for the test environment. + * + * @return the harness QAConfig <code>object</code> + */ + public QAConfig getConfig() { + return config; + } + + /** + * This method is called by the <code>MasterTest</code> immediately before + * the run method is called. Override this method to implement test specific + * construct code. This method: + * <ul> + * <li>saves a reference to <code>config</code> + * <li>starts the class server identified by the + * <code>serviceName</code> "qaClassServer" if the config value + * named <code>com.sun.jini.qa.harness.runkitserver</code> is + * <code>true</code> (the default) + * <li>starts the class server identified by the + * <code>serviceName</code> "jiniClassServer" if the config value + * named <code>com.sun.jini.qa.harness.runjiniserver</code> is + * <code>true</code> (the default) + * </ul> + * <P> + * In the majority of cases this method will be overridden. The first action + * taken by the method should be a call to + * <code>super.construct(sysConfig)</code>. + * + * @throws Exception if any failure occurs during construct + */ + public Test construct(QAConfig config) throws Exception { + int delayTime = + config.getIntConfigVal("com.sun.jini.qa.harness.startDelay", 0); + if (delayTime > 0) { + try { + Thread.sleep(1000 * delayTime); + } catch (InterruptedException ignore) { + Thread.currentThread().interrupt(); + } + } + this.config = config; + manager = new AdminManager(config); + if (config.getBooleanConfigVal("com.sun.jini.qa.harness.runkitserver", + true)) + { + getManager().startService("qaClassServer"); + SlaveRequest request = new StartClassServerRequest("qaClassServer"); + SlaveTest.broadcast(request); + } + if (config.getBooleanConfigVal("com.sun.jini.qa.harness.runjiniserver", + true)) + { + getManager().startService("jiniClassServer"); + SlaveRequest request = + new StartClassServerRequest("jiniClassServer"); + SlaveTest.broadcast(request); + } + String testClassServer = + config.getStringConfigVal("com.sun.jini.qa.harness.testClassServer", + ""); + if (testClassServer.trim().length() > 0) { + getManager().startService("testClassServer"); + SlaveRequest request = + new StartClassServerRequest(testClassServer); + SlaveTest.broadcast(request); + } + return new Test(){ + + public void run() throws Exception { + // Do nothing + } + + }; + } + + /** + * This method is called by the <code>MasterTest</code> immediately after + * the run method returns. Override this method to implement test specific + * cleanup code. This method cancels all tracked leases, destroys all + * services that were started by the <code>AdminManager</code>, and sends + * a <code>TeardownRequest</code> to all participating + * <code>SlaveTest</code>s. + * <p> + * If this method is overridden, the overriding method should include + * a call to <code>super.teardown()</code>. In most cases, this will + * be done as the final action of the overriding method, since test specific + * cleanup may depend on access to services destroyed by this method. + */ + public void tearDown() { + cancelTrackedLeases(); + if (getManager() != null) { // null if test didn't call super.construct + try { + logger.log(Level.FINE, + "Destroying remaining managed services"); + getManager().destroyAllServices(); + } catch (Exception ex) { + logger.log(Level.INFO, + "Unexpected exception while cleaning up services", + ex); + } + } + SlaveTest.broadcast(new TeardownRequest()); + } + + /** + * Track a lease for automatic cancellation when the test ends. + * + * @param lease the Lease to add to the tracking array + */ + public void trackLease(Lease lease) { + synchronized (leaseArray){ + leaseArray.add(lease); + } + } + + /** + * Cancel all Leases that have been tracked by the caller. + * <code>UnknownLeaseExceptions</code> are silently ignored. + * <code>RemoteExceptions</code> cause an error message to + * be written to the log. In all cases, all of the tracked + * leases are discarded. + */ + public void cancelTrackedLeases() { + // copy leaseArray to avoid calling remote method while synchronized. + Collection<Lease> cancel; + synchronized (leaseArray){ + cancel = new ArrayList<Lease>(leaseArray.size()); + cancel.addAll(leaseArray); + leaseArray.clear(); + } + Iterator<Lease> iter = cancel.iterator(); + while (iter.hasNext()) { + Lease lease = iter.next(); + try { + lease.cancel(); + } catch (UnknownLeaseException ignore) { + } catch (RemoteException ex) { + logger.log(Level.INFO, "Failed to cancel lease", ex); + } + } + } + + // delay is done here in case multiple groups are present + public void forceThreadDump() { + Iterator it = getManager().iterator(); + while (it.hasNext()) { + Object admin = it.next(); + if (admin instanceof NonActivatableGroupAdmin) { + if (((NonActivatableGroupAdmin) admin).forceThreadDump()) { + try { + Thread.sleep(5000); // give it time to flush + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + } + + /** + * @return the manager + */ + protected AdminManager getManager() { + return manager; + } + +}
Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/RunningServiceAdmin.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/RunningServiceAdmin.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/RunningServiceAdmin.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/RunningServiceAdmin.java Sun Oct 26 13:17:28 2014 @@ -1,211 +1,212 @@ -/* - * 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.qa.harness; - -import java.io.IOException; - -// java.util -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.logging.Level; -import java.util.NoSuchElementException; - -// net.jini -import net.jini.core.lookup.ServiceRegistrar; -import net.jini.core.lookup.ServiceTemplate; -import net.jini.discovery.LookupDiscoveryManager; -import net.jini.discovery.DiscoveryListener; -import net.jini.discovery.DiscoveryEvent; - -// java.rmi -import java.rmi.RemoteException; - -/** - * A specialization of <code>AbstractServiceAdmin</code> which obtains a proxy - * for a running service rather than starting a service directly. The parameters - * which define the service are obtained as described in {@link - * com.sun.jini.qa.harness.AbstractServiceAdmin}. Only two service properties - * supported by <code>AbstractServiceAdmin</code> are used: - * <table> - * <tr><td> tojoin - * <td> the set of groups and locators to be used to lookup - * the service. This parameter is optional, and defaults - * to the public group. - * <tr><td> impl - * <td> the name of a service class which is to be found - * in a <code>ServiceRegistrar</code>. Typically - * this would be the same as the value passed in - * the <code>serviceName</code> parameter in the - * constructor. This parameter is mandatory. - * </table> - * Group names specified in the <code>tojoin</code> parameter are never - * modified to make them unique. - */ -//XXX NOTE: this admin has never been used or tested -public class RunningServiceAdmin extends AbstractServiceAdmin implements Admin { - - /** the service proxy */ - private Object serviceRef; - - /** the map for managing discovery events */ - private LinkedList eventList; - - /** the test properties */ - private QAConfig config; - - /** the service name */ - private String serviceName; - - /** the service instance count */ - private int index; - - /** - * Construct a <code>RunningServiceAdmin</code>. - * - * @param config the configuration object for this test run - * @param serviceName the prefix used to build the property - * names needed to acquire service parameters - * @param index the instance number for this service - */ - public RunningServiceAdmin(QAConfig config, - String serviceName, - int index) - { - super(config, serviceName, index); - } - - /** - * 'Starts' a service by looking it up in a lookup service and saving the - * service proxy. The contents of the <code>tojoin</code> property is used - * to define the groups/locators to be used to locate the lookup - * service. The value of the <code>running</code> property is the name of - * the class to use for performing the lookup. A class of this name must be - * accessible by this class. The groups and locators contained in - * <code>tojoin</code> are used to create a - * <code>LookupDiscoveryManager</code>, and discovery events are processed - * in the order received. As soon as a LUS is found containing a match to - * the class named in <code>running</code>, discovery is terminated and the - * service proxy is saved. - * <p> - * The join state (group/locators) of the service is not altered. - * - * @throws TestException if the <code>running</code> parameter is not - * found or is not the name of a class accessible - * to this class. - * @throws RemoteException never. Any <code>RemoteException</code> which - * occurs while attempting to find the service - * will be wrapped in a <code>TestException</code>. - */ - public void start() throws RemoteException, TestException { - if (serviceRef != null) { - throw new TestException("RunningServiceAdmin: a service has " - + "already been started by this admin"); - } - Class[] types = null; - try { - types = new Class[]{Class.forName(getServiceImpl())}; - } catch (ClassNotFoundException e) { - throw new TestException("could not load class" - + getImpl() + " identified by " - + serviceName + ".impl", - e); - } - eventList = new LinkedList(); // every start call gets a new list - DiscoveryListener listener = new RunningDiscoveryListener(); - LookupDiscoveryManager manager = null; - // populate the groups/locators arrays. Discard the overrides list. - // This admin implement doRandom to return false to inhibit - // randomization of the group names - addServiceGroupsAndLocators(new ArrayList()); - try { - manager = new LookupDiscoveryManager(getGroups(), - getLocators(), - listener); - } catch (IOException e) { - throw new TestException("failed to create a LookupDiscoveryManager", - e); - } - logServiceParameters(); - ServiceTemplate template = new ServiceTemplate(null, types, null); - while (true) { - DiscoveryEvent event = null; - synchronized (eventList) { - try { - event = (DiscoveryEvent) eventList.removeFirst(); - } catch (NoSuchElementException e) { - try { - eventList.wait(); // XXX timeout? - } catch (InterruptedException ie) { - } - } - } - if (event != null) { - ServiceRegistrar[] registrars = event.getRegistrars(); - for (int i = registrars.length; --i >= 0; ) { - ServiceRegistrar registrar = registrars[i]; - serviceRef = registrar.lookup(template); - if (serviceRef != null) { - manager.terminate(); - return; - } - } - } - } - } - - /** - * Stop the service. Since the service was started externally, it is - * presumed that the service must also be stopped externally. Therefore, - * this method simply clears the internal reference to the service - * proxy and does not attempt to actually stop the service. - * - * @throws RemoteException never - */ - public void stop() throws RemoteException { - serviceRef = null; - } - - // inherit javadoc - public Object getProxy() { - return serviceRef; - } - - /** - * An implementation of <code>DiscoveryListener</code> whose - * <code>discovered</code> method simply places <code>DiscoveryEvent</code>s - * on a list for processing by the <code>start</code> method. - */ - private class RunningDiscoveryListener implements DiscoveryListener { - - public void discarded(DiscoveryEvent e) { - } - - public void discovered(DiscoveryEvent e) { - synchronized (eventList) { - eventList.addLast(e); - eventList.notify(); - } - } - } - - /* inherit javadoc */ - protected boolean doRandom() { - return false; - } -} +/* + * 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.qa.harness; + +import java.io.IOException; + +// java.util +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.logging.Level; +import java.util.NoSuchElementException; + +// net.jini +import net.jini.core.lookup.ServiceRegistrar; +import net.jini.core.lookup.ServiceTemplate; +import net.jini.discovery.LookupDiscoveryManager; +import net.jini.discovery.DiscoveryListener; +import net.jini.discovery.DiscoveryEvent; + +// java.rmi +import java.rmi.RemoteException; + +/** + * A specialization of <code>AbstractServiceAdmin</code> which obtains a proxy + * for a running service rather than starting a service directly. The parameters + * which define the service are obtained as described in {@link + * com.sun.jini.qa.harness.AbstractServiceAdmin}. Only two service properties + * supported by <code>AbstractServiceAdmin</code> are used: + * <table> + * <tr><td> tojoin + * <td> the set of groups and locators to be used to lookup + * the service. This parameter is optional, and defaults + * to the public group. + * <tr><td> impl + * <td> the name of a service class which is to be found + * in a <code>ServiceRegistrar</code>. Typically + * this would be the same as the value passed in + * the <code>serviceName</code> parameter in the + * constructor. This parameter is mandatory. + * </table> + * Group names specified in the <code>tojoin</code> parameter are never + * modified to make them unique. + */ +//XXX NOTE: this admin has never been used or tested +public class RunningServiceAdmin extends AbstractServiceAdmin implements Admin { + + /** the service proxy */ + private Object serviceRef; + + /** the map for managing discovery events */ + private LinkedList eventList; + + /** the test properties */ + private QAConfig config; + + /** the service name */ + private String serviceName; + + /** the service instance count */ + private int index; + + /** + * Construct a <code>RunningServiceAdmin</code>. + * + * @param config the configuration object for this test run + * @param serviceName the prefix used to build the property + * names needed to acquire service parameters + * @param index the instance number for this service + */ + public RunningServiceAdmin(QAConfig config, + String serviceName, + int index) + { + super(config, serviceName, index); + } + + /** + * 'Starts' a service by looking it up in a lookup service and saving the + * service proxy. The contents of the <code>tojoin</code> property is used + * to define the groups/locators to be used to locate the lookup + * service. The value of the <code>running</code> property is the name of + * the class to use for performing the lookup. A class of this name must be + * accessible by this class. The groups and locators contained in + * <code>tojoin</code> are used to create a + * <code>LookupDiscoveryManager</code>, and discovery events are processed + * in the order received. As soon as a LUS is found containing a match to + * the class named in <code>running</code>, discovery is terminated and the + * service proxy is saved. + * <p> + * The join state (group/locators) of the service is not altered. + * + * @throws TestException if the <code>running</code> parameter is not + * found or is not the name of a class accessible + * to this class. + * @throws RemoteException never. Any <code>RemoteException</code> which + * occurs while attempting to find the service + * will be wrapped in a <code>TestException</code>. + */ + public void start() throws RemoteException, TestException { + if (serviceRef != null) { + throw new TestException("RunningServiceAdmin: a service has " + + "already been started by this admin"); + } + Class[] types = null; + try { + types = new Class[]{Class.forName(getServiceImpl())}; + } catch (ClassNotFoundException e) { + throw new TestException("could not load class" + + getImpl() + " identified by " + + serviceName + ".impl", + e); + } + eventList = new LinkedList(); // every start call gets a new list + DiscoveryListener listener = new RunningDiscoveryListener(); + LookupDiscoveryManager manager = null; + // populate the groups/locators arrays. Discard the overrides list. + // This admin implement doRandom to return false to inhibit + // randomization of the group names + addServiceGroupsAndLocators(new ArrayList()); + try { + manager = new LookupDiscoveryManager(getGroups(), + getLocators(), + listener); + } catch (IOException e) { + throw new TestException("failed to create a LookupDiscoveryManager", + e); + } + logServiceParameters(); + ServiceTemplate template = new ServiceTemplate(null, types, null); + while (true) { + DiscoveryEvent event = null; + synchronized (eventList) { + try { + event = (DiscoveryEvent) eventList.removeFirst(); + } catch (NoSuchElementException e) { + try { + eventList.wait(); // XXX timeout? + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + } + if (event != null) { + ServiceRegistrar[] registrars = event.getRegistrars(); + for (int i = registrars.length; --i >= 0; ) { + ServiceRegistrar registrar = registrars[i]; + serviceRef = registrar.lookup(template); + if (serviceRef != null) { + manager.terminate(); + return; + } + } + } + } + } + + /** + * Stop the service. Since the service was started externally, it is + * presumed that the service must also be stopped externally. Therefore, + * this method simply clears the internal reference to the service + * proxy and does not attempt to actually stop the service. + * + * @throws RemoteException never + */ + public void stop() throws RemoteException { + serviceRef = null; + } + + // inherit javadoc + public Object getProxy() { + return serviceRef; + } + + /** + * An implementation of <code>DiscoveryListener</code> whose + * <code>discovered</code> method simply places <code>DiscoveryEvent</code>s + * on a list for processing by the <code>start</code> method. + */ + private class RunningDiscoveryListener implements DiscoveryListener { + + public void discarded(DiscoveryEvent e) { + } + + public void discovered(DiscoveryEvent e) { + synchronized (eventList) { + eventList.addLast(e); + eventList.notify(); + } + } + } + + /* inherit javadoc */ + protected boolean doRandom() { + return false; + } +} Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/ServiceDestroyer.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/ServiceDestroyer.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/ServiceDestroyer.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/ServiceDestroyer.java Sun Oct 26 13:17:28 2014 @@ -1,157 +1,159 @@ -/* - * 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.qa.harness; - -import com.sun.jini.admin.DestroyAdmin; -import com.sun.jini.start.SharedActivatableServiceDescriptor.Created; - -import java.rmi.activation.ActivationException; -import java.rmi.activation.ActivationSystem; -import java.rmi.activation.UnknownObjectException; -import java.rmi.activation.ActivationGroup; -import java.rmi.RemoteException; - -import net.jini.admin.Administrable; -import net.jini.config.Configuration; - -/** - * This class provides static methods that can be used to destroy a service. - * This implementation was taken from the <code>com.sun.jini.start</code> - * package when it became obsolete there. - */ -class ServiceDestroyer { - - static final int DESTROY_SUCCESS = 0; - /* Failure return codes */ - static final int SERVICE_NOT_ADMINISTRABLE = -1; - static final int SERVICE_NOT_DESTROY_ADMIN = -2; - static final int DEACTIVATION_TIMEOUT = -3; - static final int PERSISTENT_STORE_EXISTS = -4; - - static final int N_MS_PER_SEC = 1000; - static final int DEFAULT_N_SECS_WAIT = 600; - - /** - * 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>true</code> if the service's destroy method was invoked - * successfully; <code>false</code> otherwise. - * - * @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. - */ - 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 <code>Created</code> object returned when the - * service was started - * @param nSecsWait the number of seconds to wait for the service's - * activation descriptor to be no longer registered with - * the activation system - * @param config a <code>Configuration</code> object which is unused - * and probably present only for historical reasons - * - * @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 - */ - static int destroy(Created created, int nSecsWait, Configuration config) - 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(1*N_MS_PER_SEC); - } catch (InterruptedException e) { } - } - if(!deactivated) return DEACTIVATION_TIMEOUT; - return DESTROY_SUCCESS; - } -} - +/* + * 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.qa.harness; + +import com.sun.jini.admin.DestroyAdmin; +import com.sun.jini.start.SharedActivatableServiceDescriptor.Created; + +import java.rmi.activation.ActivationException; +import java.rmi.activation.ActivationSystem; +import java.rmi.activation.UnknownObjectException; +import java.rmi.activation.ActivationGroup; +import java.rmi.RemoteException; + +import net.jini.admin.Administrable; +import net.jini.config.Configuration; + +/** + * This class provides static methods that can be used to destroy a service. + * This implementation was taken from the <code>com.sun.jini.start</code> + * package when it became obsolete there. + */ +class ServiceDestroyer { + + static final int DESTROY_SUCCESS = 0; + /* Failure return codes */ + static final int SERVICE_NOT_ADMINISTRABLE = -1; + static final int SERVICE_NOT_DESTROY_ADMIN = -2; + static final int DEACTIVATION_TIMEOUT = -3; + static final int PERSISTENT_STORE_EXISTS = -4; + + static final int N_MS_PER_SEC = 1000; + static final int DEFAULT_N_SECS_WAIT = 600; + + /** + * 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>true</code> if the service's destroy method was invoked + * successfully; <code>false</code> otherwise. + * + * @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. + */ + 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 <code>Created</code> object returned when the + * service was started + * @param nSecsWait the number of seconds to wait for the service's + * activation descriptor to be no longer registered with + * the activation system + * @param config a <code>Configuration</code> object which is unused + * and probably present only for historical reasons + * + * @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 + */ + static int destroy(Created created, int nSecsWait, Configuration config) + 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(1*N_MS_PER_SEC); + } catch (InterruptedException e){ + Thread.currentThread().interrupt(); + } + } + if(!deactivated) return DEACTIVATION_TIMEOUT; + return DESTROY_SUCCESS; + } +} +
