/*
* 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 com.sun.jini.qa.harness.QATest;
import com.sun.jini.test.share.DiscoveryProtocolSimulator;
import com.sun.jini.test.share.DiscoveryServiceUtil;
import com.sun.jini.test.share.GroupsUtil;
import com.sun.jini.test.share.LocatorsUtil;
import com.sun.jini.qa.harness.QAConfig;
import com.sun.jini.qa.harness.TestException;
import net.jini.admin.Administrable;
import net.jini.admin.JoinAdmin;
import net.jini.discovery.DiscoveryManagement;
import net.jini.discovery.DiscoveryGroupManagement;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryChangeListener;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.LookupDiscoveryService;
import net.jini.lookup.DiscoveryAdmin;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceRegistrar;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
/**
* This class is an abstract class that contains common functionality
* related to setup and tearDown that may be useful to many of tests.
* acts as the base class which
*
* This abstract class contains various static inner classes, any one
* of which can be used as a listener to participate in the lookup
* service discovery process on behalf of the tests that sub-class this
* abstract class.
* <p>
* This class provides an implementation of both the <code>setup</code> method
* and the <code>tearDown</code> method, which perform -- respectively --
* standard functions related to the initialization and clean up of the
* system state necessary to execute the test.
*
* @see com.sun.jini.qa.harness.QAConfig
* @see com.sun.jini.qa.harness.QATest
*/
abstract public class BaseQATest extends QATest {
protected static final int AUTOMATIC_LOCAL_TEST = Integer.MAX_VALUE;
protected static final int MANUAL_TEST_REMOTE_COMPONENT = 1;
protected static final int MANUAL_TEST_LOCAL_COMPONENT = 2;
protected boolean useFastTimeout = false;//for faster completion
protected int fastTimeout = 10;//default value
protected boolean displayOn = true;//verbose in waitForDiscovery/Discard
protected boolean debugsync = false;//turns on synchronization debugging
/** Ordered pair containing a LookupLocator and the corresponding groups */
public class LocatorGroupsPair {
public LookupLocator locator;
public String[] groups;
public LocatorGroupsPair(LookupLocator locator, String[] groups) {
this.locator = locator;
this.groups = groups;
}//end constructor
public boolean equals(Object obj) {
if(this == obj) return true;
if( !(obj instanceof LocatorGroupsPair) ) return false;
if(!((LocatorGroupsPair)obj).locator.equals(locator)) return false;
return GroupsUtil.compareGroupSets(groups,
((LocatorGroupsPair)obj).groups, Level.OFF);
}//end equals
}//end class LocatorGroupsPair
/** Data structure representing a set of LookupLocators & groups to join */
public class ToJoinPair {
public LookupLocator[] locators;
public String[] groups;
public ToJoinPair(LookupLocator[] locators, String[] groups) {
this.locators = locators;
this.groups = groups;
}//end constructor
public ToJoinPair(LookupLocator[] locators) {
this.locators = locators;
this.groups = DiscoveryGroupManagement.NO_GROUPS;
}//end constructor
public ToJoinPair(String[] groups) {
this.locators = new LookupLocator[0];
this.groups = groups;
}//end constructor
}//end class ToJoinPair
/** Listener class used to monitor the discovery events sent from the
* helper utility that, on behalf of the test, participates in the
* multicast discovery protocol. Note that in most cases, the
* test cannot proceed until at least one discovery event containing
* at least one reference to a ServiceRegistrar is received. This class
* provides information that allows the test to determine whether or
* not to proceed.
*/
protected class LookupListener implements DiscoveryListener {
public LookupListener(){ }
public HashMap discoveredMap = new HashMap(11);
public HashMap discardedMap = new HashMap(11);
public HashMap expectedDiscoveredMap = new HashMap(11);
public HashMap expectedDiscardedMap = new HashMap(11);
/** Returns the locators of the lookups from discoveredMap, which
* contains both the lookups that are expected to be discovered,
* as well as the lookups that have already been discovered.
*/
public LookupLocator[] getDiscoveredLocators() {
synchronized(this) {
Set kSet = discoveredMap.keySet();
return ((LookupLocator[])(kSet).toArray
(new LookupLocator[kSet.size()]));
}//end sync(this)
}//end getDiscoveredLocators
/** Returns the locators that are expected to be discovered, but which
* have not yet been discovered.
*/
/** Returns the locators of the lookups from expectedDiscoveredMap that
* are not also in discoveredMap; this method returns the locators
* of the lookups that are expected to be discovered, but which
* have not yet been discovered.
*/
public LookupLocator[] getUndiscoveredLocators() {
synchronized(this) {
Set dSet = discoveredMap.keySet();
Set eSet = expectedDiscoveredMap.keySet();
ArrayList uLocsList = new ArrayList(eSet.size());
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
LookupLocator loc = (LookupLocator)iter.next();
if( !dSet.contains(loc) ) uLocsList.add(loc);
}//end loop
return ((LookupLocator[])(uLocsList).toArray
(new LookupLocator[uLocsList.size()]));
}//end sync(this)
}//end getUndiscoveredLocators
public void clearAllEventInfo() {
synchronized(this) {
discoveredMap.clear();
discardedMap.clear();
expectedDiscoveredMap.clear();
expectedDiscardedMap.clear();
}//end sync(this)
}//end clearAllEventInfo
public void clearDiscoveryEventInfo() {
synchronized(this) {
discoveredMap.clear();
expectedDiscoveredMap.clear();
}//end sync(this)
}//end clearDiscoveryEventInfo
public void clearDiscardEventInfo() {
synchronized(this) {
discardedMap.clear();
expectedDiscardedMap.clear();
}//end sync(this)
}//end clearDiscardEventInfo
/** Use this method to set the contents of the discoveredMap to a
* specific set of values.
*/
public void setDiscoveredMap(ArrayList locGroupsList) {
synchronized(this) {
discoveredMap.clear();
discardedMap.clear();
for(int i=0;i<locGroupsList.size();i++) {
LocatorGroupsPair pair =
(LocatorGroupsPair)locGroupsList.get(i);
discoveredMap.put(pair.locator,pair.groups);
}//end loop
}//end sync(this)
}//end setDiscoveredMap
/** Use this method to set the contents of both the discoveredMap
* and the expectedDiscardedMap to a specific set of values.
*/
public void setDiscardEventInfo(ArrayList locGroupsList) {
synchronized(this) {
discoveredMap.clear();
discardedMap.clear();
for(int i=0;i<locGroupsList.size();i++) {
LocatorGroupsPair pair =
(LocatorGroupsPair)locGroupsList.get(i);
/* Have to set discoveredMap so that discarded() method
* will place discarded lookup in the discardedMap when
* the discarded event arrives.
*/
discoveredMap.put(pair.locator,pair.groups);
expectedDiscardedMap.put(pair.locator,pair.groups);
}//end loop
}//end sync(this)
}//end clearDiscardEventInfo
/** This method should be called whenever the lookups this listener
* is supposed to discover are changed during a test. This method
* examines the new lookups to discover and then re-sets the
* current and/or expected state of the fields of this class related
* to the discovered/discarded event state of this listener.
*/
public void setLookupsToDiscover(ArrayList locGroupsList) {
setLookupsToDiscover(locGroupsList,
toLocatorArray(allLookupsToStart),
toGroupsArray(allLookupsToStart));
}//end setLookupsToDiscover
public void setLookupsToDiscover(ArrayList locGroupsList,
LookupLocator[] locatorsToDiscover)
{
setLookupsToDiscover(locGroupsList,
locatorsToDiscover,
DiscoveryGroupManagement.NO_GROUPS);
}//end setLookupsToDiscover
public void setLookupsToDiscover(ArrayList locGroupsList,
String[] groupsToDiscover)
{
setLookupsToDiscover(locGroupsList,
new LookupLocator[0],
groupsToDiscover);
}//end setLookupsToDiscover
public void setLookupsToDiscover(ArrayList locGroupsList,
LookupLocator[] locatorsToDiscover,
String[] groupsToDiscover)
{
synchronized(this) {
LookupLocator[] locators = toLocatorArray(locGroupsList);
boolean discoverAll = discoverAllLookups(locGroupsList,
groupsToDiscover);
/* The input ArrayList contains (locator,groups) pairs that
* represent the locator and current member groups of lookup
* services that have been started. Those lookup services
* that satisfy one or both of the following conditions
* either are expected to be discovered, or have already been
* discovered:
* - the lookup's corresponding locator is referenced in the
* locatorsToDiscover parameter
* - the lookup's current member groups consist of one or
* more of the groups referenced in the groupsToDiscover
* parameter
* The (locator,groups) pairs from the ArrayList that
* correspond to such lookup services are placed in the set
* that contains information related to the lookup services
* that are expected to be discovered.
*/
for(int i=0;i<locGroupsList.size();i++) {
LocatorGroupsPair pair =
(LocatorGroupsPair)locGroupsList.get(i);
LookupLocator curLoc = pair.locator;
String[] curGroups = pair.groups;
if( discoverByLocators(curLoc,locatorsToDiscover)
|| discoverAll
|| discoverByGroups(curGroups,groupsToDiscover) )
{
expectedDiscoveredMap.put(curLoc,curGroups);
}//endif
}//end loop
/* The input ArrayList contains (locator,groups) pairs that
* represent the locator and current member groups of lookup
* services that have been started. The referenced lookup
* services may have been previously discovered, and the
* current member groups may reflect some change from when
* the lookup service was previously discovered. The
* discoveredMap for this listener contains (locator,groups)
* pairs that correspond to lookup services that actually have
* been previously DISCOVERED through either locator discovery
* or through group discovery of the original member groups of
* the lookup service (or both).
*
* For any (locator,groups) pair from the discoveredMap,
* the corresponding lookup service can become no longer of
* interest. This occurs when both of the following conditions
* occur:
* - the lookup's corresponding locator is NOT referenced in
* the locatorsToDiscover parameter (so there is no
* interest in discovering that lookup service using
* locator discovery)
* - the lookup's current member groups consist of NONE of
* the groups referenced in the groupsToDiscover parameter
* (so there is no interest in discovering that lookup
* service using group discovery)
*
* Note that loss of interest in using group discovery to
* discover the lookup service can occur when one or both of
* the following conditions occurs:
* - the lookup's current member groups has changed
* - the contents of the groupsToDiscover parameter has
* changed
*
* When a combination of conditions - as described above -
* indicate that a previously discovered lookup service
* (corresponding to an element of the discoveredMap) is
* no longer of interest through either locator discovery
* or group discovery (or both), the lookup service will
* eventually be discarded. Thus, the corresponding
* (locator,groups) pair should be REMOVED from the
* expectedDiscoveredMap, and a pair having that lookup's
* corresponding locator and current member groups should
* be placed in the expectedDiscardedMap.
*
* Thus, for our purposes here, there are three conditions
* in which the lookup service will no longer be of interest:
* -- the element of discoveredMap, corresponding to the
* lookup service in question, corresponds to NONE of the
* elements of the input ArrayList
* -- the locator of the lookup service in question
* equals NONE of the elements of the locatorsToDiscover
* parameter
* -- NONE of the current member groups of the lookup
* service in question equal any of the elements of the
* groupsToDiscover parameter
*/
Set eSet = discoveredMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
/* We care what the current member groups are now, as
* indicated by the contents of the input ArrayList;
* not the member groups that were originally discovered.
* If the groups of a previously discovered lookup, and/or
* the groupsToDiscover have changed in such a way that
* interest in the previously discovered lookup service
* has ceased (and we are not currently interested in
* discovering that lookup service using locator
* discovery), then we should expect that lookup service
* to be discarded.
*
* Below, the current locator from the set of previously
* discovered lookups is used to determine the current
* member groups of that lookup service. If that locator
* is contained in the input ArrayList, then the groups
* paired with the locator in that ArrayList are considered
* the most current; and they are used to determine if
* we are still interested in the lookup service. If that
* locator is not referenced in the input ArrayList, then
* we assume the lookup's current member groups are the
* groups associated with the locator when the lookup
* service was previously discovered; and those original
* groups are used to determine if we are still interested
* in the lookup service.
*/
String[] memberGroups = getGroups(loc,locGroupsList);
if(memberGroups == null) {
memberGroups = (String[])pair.getValue();
}//endif
if(isElementOf(loc,locators) &&
( discoverByLocators(loc,locatorsToDiscover)
|| discoverAll
|| discoverByGroups(memberGroups,groupsToDiscover)) )
{
continue;//still interested, go to next
}//endif
/* not interested in this lookup anymore, expect discard */
expectedDiscoveredMap.remove(loc);
expectedDiscardedMap.put(loc,memberGroups);
}//end loop
/* The input ArrayList contains (locator,groups) pairs that
* represent the locator and current member groups of lookup
* services that have been started. The referenced lookup
* services may have been previously discardred, and the
* current member groups may reflect some change from when
* the lookup service was previously discardred. The
* discardedMap for this listener contains (locator,groups)
* pairs that correspond to lookup services that actually have
* been previously DISCARDED for various reasons (no longer
* interested in that lookup's locator, groups have changed,
* announcements have stopped, etc.).
*
* For any (locator,groups) pair from the discardedMap,
* the corresponding lookup service can change from not
* being of interest to now being of interest. This occurs
* when one of both of the following conditions occur:
* - the lookup's corresponding locator is NOW referenced in
* the locatorsToDiscover parameter (so there is new
* interest in discovering that lookup service using
* locator discovery)
* - the lookup's current member groups consist of AT LEAST
* ONE of the groups referenced in the groupsToDiscover
* parameter (so there is new interest in discovering
* that lookup service using group discovery)
*
* Note that renewed interest in using group discovery to
* discover the lookup service can occur when one or both of
* the following conditions occurs:
* - the lookup's current member groups has changed
* - the contents of the groupsToDiscover parameter has
* changed
*
* When a combination of conditions - as described above -
* indicate that a previously discarded lookup service
* (corresponding to an element of the discardedMap) is
* now of interest through either locator discovery or group
* discovery (or both), the lookup service will eventually be
* re-discovered. Thus, the corresponding (locator,groups)
* pair should be REMOVED from the expectedDiscardedMap, and
* a pair having that lookup's corresponding locator and
* current member groups should be placed in the
* expectedDiscoveredMap.
*
* Thus, for our purposes here, there are three conditions
* that must be met for the status of the lookup service to
* change from 'not of interest' to 'now of interest':
* -- the element of discardedMap, corresponding to the
* lookup service in question, must correspond to an
* element of the input ArrayList
* -- the locator of the lookup service in question must
* equal one of the elements of the locatorsToDiscover
* parameter
* -- at least ONE of the current member groups of the lookup
* service in question must equal one of the elements
* of the groupsToDiscover parameter
*/
eSet = discardedMap.entrySet();
iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
/* We care what the current member groups are now, as
* indicated by the contents of the input ArrayList;
* not the member groups that were originally discarded.
* If the groups of a previously discarded lookup, and/or
* the groupsToDiscover have changed in such a way that
* we are now again interested in re-discovering the
* previously discarded lookup service (or we are now
* currently interested in discovering that lookup service
* using locator discovery), then we should expect that
* lookup service to be re-discovered.
*
* Below, the current locator from the set of previously
* discarded lookups is used to determine the current
* member groups of that lookup service. If that locator
* is contained in the input ArrayList, then the groups
* paired with the locator in that ArrayList are considered
* the most current; and they are used to determine if
* we are still interested in the lookup service. If that
* locator is not referenced in the input ArrayList, then
* we assume the lookup's current member groups are the
* groups associated with the locator when the lookup
* service was previously discarded; and those original
* groups are used to determine if we are still interested
* in the lookup service.
*/
String[] memberGroups = getGroups(loc,locGroupsList);
if(memberGroups == null) {
memberGroups = (String[])pair.getValue();
}//endif
if( !isElementOf(loc,locators) ||
( !discoverByLocators(loc,locatorsToDiscover)
&& !discoverAll
&& !discoverByGroups(memberGroups,groupsToDiscover)))
{
continue;//still not interested, go to next
}//endif
/* now interested in this lookup, expect re-discovery */
expectedDiscardedMap.remove(loc);
expectedDiscoveredMap.put(loc,memberGroups);
}//end loop
}//end sync(this)
}//end setLookupsToDiscover
/** Returns all of the groups (duplicates removed), across all lookup
* services, that are currently expected to be discovered.
*/
String[] getCurExpectedDiscoveredGroups() {
HashSet groupSet = new HashSet(expectedDiscoveredMap.size());
Set eSet = expectedDiscoveredMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
String[] curGroups = (String[])pair.getValue();
for(int i=0;i<curGroups.length;i++) {
groupSet.add(curGroups[i]);
}//end loop
}//end loop
return ((String[])(groupSet).toArray(new String[groupSet.size()]));
}//end getCurExpectedDiscoveredGroups
public void discovered(DiscoveryEvent evnt) {
/* the LDM (actually, its ld) has already prepared these registrars */
ServiceRegistrar[] regs = evnt.getRegistrars();
if(regs != null) {
logger.log(Level.FINE, " discovery event received "
+"-- "+regs.length+" lookup(s)");
Map groupsMap = evnt.getGroups();
synchronized(this) {
boolean oneDiscovered = false;
ArrayList lusList = getLookupListSnapshot
("BaseQATest$LookupListenter.discovered");
for(int i=0;i<regs.length;i++) {
LookupLocator loc = null;
String[] groups = null;
boolean lookupOK = false;
if( lusList.contains(regs[i]) ) {
logger.log(Level.FINE,
" regs["+i+"] is in lookupList");
lookupOK = true;
} else {
logger.log(Level.FINE,
" regs["+i+"] is NOT in lookupList");
}//endif
if( lookupOK
|| (testType == MANUAL_TEST_LOCAL_COMPONENT) )
{
/* it's either a lookup started by the test, or
* it may be a remote lookup of interest
*/
try {
loc = QAConfig.getConstrainedLocator(regs[i].getLocator());
groups = (String[])groupsMap.get(regs[i]);
/* Recall that when lookups are started, they
* are first started using a default port and
* belonging to NO_GROUPS, and then the port
* and member groups are set -- IN THAT ORDER.
* Because of this, when using an LLD to
* discover lookups by locator, it's
* theoretically possible that a discovery
* event may arrive with the configured port,
* but belonging to NO_GROUPS. This can happen
* when the unicast exchange between the LLD
* and the lookup occurs between the time the
* lookup is started and the port is set, and
* the time the member groups are set to the
* configured member groups. Because of this,
* the groups arriving in the discovery event
* are tested for NO_GROUPS (which may be what
* was actually intended, or may indicate that
* the groups have not been set yet). If the
* groups are NO_GROUPS, wait N seconds to
* allow the groups to be set, then query
* the lookup service for its member groups so
* as to guarantee that the discoveredMap has
* the actual member groups that were intended.
*/
if(groups.length == 0) {
logger.log(Level.FINE,
" NO_GROUPS in event ... wait 5 "
+"seconds for member groups to be set");
DiscoveryServiceUtil.delayMS(5000);
logger.log(Level.FINE,
" wait period complete ... retrieving "
+"member groups from regs["+i+"]");
groups = regs[i].getGroups();
}//endif
} catch(Exception e) { e.printStackTrace(); }
if( !lookupOK &&
(testType == MANUAL_TEST_LOCAL_COMPONENT))
{
/* determine if it's a LUS of interest */
LookupLocator[] locsToDiscover
= toLocatorArray(allLookupsToStart);
if(isElementOf(loc,locsToDiscover)) {
lookupOK = true;//is lookup of interest
}//endif
}//endif
}//endif
/* care only about the lookups of interest */
if( !lookupOK ) continue;
discardedMap.remove(loc);
discoveredMap.put(loc,groups);
LocatorsUtil.displayLocator(loc,
" discovered locator",
Level.FINE);
logger.log(Level.FINE,
" discovered member group(s) = "
+GroupsUtil.toCommaSeparatedStr(groups));
oneDiscovered = true;
}//end loop
if(oneDiscovered) {
logger.log(Level.FINE,
" number of currently discovered lookup(s) = "
+discoveredMap.size());
}
}//end sync(this)
} else {//(regs == null)
logger.log(Level.FINE, " discovery event received "
+"-- event.getRegistrars() returned NULL");
}//endif(regs != null)
}//end discovered
public void discarded(DiscoveryEvent evnt) {
/* the LDM (actually, its ld) has already prepared these registrars */
ServiceRegistrar[] regs = evnt.getRegistrars();
if(regs != null) {
logger.log(Level.FINE, " discard event received "
+"-- "+regs.length+" lookup(s)");
Map groupsMap = evnt.getGroups();
synchronized(this) {
for(int i=0;i<regs.length;i++) {
/* Can't make a remote call to retrieve the locator
* of the discarded registrar like what was done when
* the registrar was discovered (since it may be down)
* so get the locator from the local map of registrars
* to locators that was populated when each registrar
* was started.
*/
LocatorGroupsPair pair =
(LocatorGroupsPair)regsToLocGroupsMap.get(regs[i]);
if(pair == null) continue;//lookup started outside test
LookupLocator loc = pair.locator;
/* Add to discardedMap only if previously discovered */
if((loc != null)&&(discoveredMap.remove(loc) != null)){
logger.log(Level.FINE,
" discarded locator = "+loc);
String[] groups = (String[])groupsMap.get(regs[i]);
logger.log(Level.FINE,
" discarded member group(s) = "
+GroupsUtil.toCommaSeparatedStr(groups));
discardedMap.put(loc,groups);
}//endif
}//end loop
logger.log(Level.FINE,
" number of currently discovered lookup(s) = "
+discoveredMap.size());
}//end sync(this)
} else {//(regs == null)
logger.log(Level.FINE, " discard event received "
+"-- event.getRegistrars() returned NULL");
}//endif(regs != null)
}//end discarded
}//end class LookupListener
/** Listener class used to monitor the following events sent from the
* helper utility that, on behalf of the test, participates in the
* multicast discovery protocols:
* <p><ul>
* <li> the discovery of new lookup services
* <li> the re-discovery of discarded lookup services
* <li> the discarding of already-discovered lookup services
* <li> member group changes in already-discovered lookup services
* </ul><p>
*/
protected class GroupChangeListener extends LookupListener
implements DiscoveryChangeListener
{
public GroupChangeListener(){ }
public HashMap changedMap = new HashMap(11);
public HashMap expectedChangedMap = new HashMap(11);
public void clearAllEventInfo() {
synchronized(this) {
super.clearAllEventInfo();
changedMap.clear();
expectedChangedMap.clear();
}//end sync(this)
}//end clearAllEventInfo
public void clearChangeEventInfo() {
synchronized(this) {
changedMap.clear();
expectedChangedMap.clear();
}//end sync(this)
}//end clearChangeEventInfo
/** This method should be called whenever the lookups this listener
* is supposed to discover are changed during a test. This method
* examines the new lookups to discover and then re-sets the
* current and/or expected state of the fields of this class related
* to the changed event state of this listener.
*/
public void setLookupsToDiscover(ArrayList locGroupsList) {
this.setLookupsToDiscover(locGroupsList,
toGroupsArray(allLookupsToStart));
}//end setLookupsToDiscover
public void setLookupsToDiscover(ArrayList locGroupsList,
String[] groupsToDiscover)
{
this.setLookupsToDiscover(locGroupsList,
new LookupLocator[0],
groupsToDiscover);
}//end setLookupsToDiscover
public void setLookupsToDiscover(ArrayList locGroupsList,
LookupLocator[] locatorsToDiscover,
String[] groupsToDiscover)
{
synchronized(this) {
super.setLookupsToDiscover(locGroupsList,
locatorsToDiscover,
groupsToDiscover);
LookupLocator[] locators = toLocatorArray(locGroupsList);
boolean discoverAll = discoverAllLookups(locGroupsList,
groupsToDiscover);
/* The input ArrayList contains (locator,groups) pairs that
* represent the locator and current member groups of lookup
* services that have been started. The referenced lookup
* services may have been previously discovered, and the
* current member groups may reflect some change from when
* the lookup service was previously discovered. The
* discoveredMap for this listener contains (locator,groups)
* pairs that correspond to lookup services that actually have
* been previously DISCOVERED through group discovery of the
* original member groups of the lookup service.
*
* For any (locator,groups) pair from the discoveredMap,
* the corresponding lookup service can experience a "change"
* in its set of member groups. This occurs when the contents
* of the lookup service's set of member groups is changed
* in such a way that its contents differs from the contents
* of the member groups associated with that lookup service, in
* the discoveredMap, but at least one of the groups in the new
* set of member groups is an element of the groupsToDiscover
* (otherwise, a discard - rather than a change - situation
* has occurred). When this does occur, the lookup discovery
* utility will notice (through the contents of the multicast
* announcements), and will send to this listener, a changed
* event that reflects the new member groups. Thus, a new
* (locator,groups) pair, corresponding to the current pair
* in the discoveredMap - but which reflects the new member
* groups, should be placed in the expectedChangedMap.
*/
Set eSet = discoveredMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] oldGroups = (String[])pair.getValue();
if( !isElementOf(loc,locators) ) continue;
String[] newGroups = getGroups(loc,locGroupsList);
if(newGroups == null) {
/* The lookup with the given loc does not appear to
* be in the given list, and we must not be interested
* in discovering it by group, skip it since we don't
* expect changed events from such a lookup, even if
* its member groups are changed.
*/
continue;
}//endif
boolean discoveredByGroup = false;
boolean discoveredByLoc = false;
if( discoverAll
|| discoverByGroups(oldGroups,groupsToDiscover) )
{
discoveredByGroup = true;
}//endif
if( discoverByLocators(loc,locatorsToDiscover) ) {
discoveredByLoc = true;
}//endif
if(discoveredByGroup) {
if(GroupsUtil.compareGroupSets(oldGroups,newGroups, Level.OFF)) {
continue;//no change in groups, go to next
}//endif
/* If we're interested in ALL_GROUPS or if the old and
* new groups intersect, then expect a changed event
*/
if( (groupsToDiscover
== DiscoveryGroupManagement.ALL_GROUPS)
|| (discoverByGroups(newGroups,oldGroups)) )
{
expectedChangedMap.put(loc,newGroups);
} else {//ALL old groups replaced with new groups
if(discoveredByLoc) {
expectedChangedMap.put(loc,newGroups);
}//endif
}//endif
} else {//discovered by only locator ==> no changed event
continue;
}//endif(discoveredByGroup)
}//end loop
}//end sync(this)
}//end setLookupsToDiscover
public void changed(DiscoveryEvent evnt) {
/* the LDM (actually, its ld) has already prepared these registrars */
ServiceRegistrar[] regs = evnt.getRegistrars();
if(regs != null) {
logger.log(Level.FINE, " change event received "
+"-- "+regs.length+" lookup(s)");
Map groupsMap = evnt.getGroups();
synchronized(this) {
boolean oneChanged = false;
ArrayList regList = getLookupListSnapshot
("BaseQATest$LookupListenter.changed");
for(int i=0;i<regs.length;i++) {
if( regList.contains(regs[i]) ) {
logger.log(Level.FINE,
" regs["+i+"] is in lookupList");
} else {
logger.log(Level.FINE,
" regs["+i+"] is NOT in lookupList");
continue;//care only about lookups the test started
}//endif
try {
LookupLocator loc = QAConfig.getConstrainedLocator(regs[i].getLocator());
String[] groups = (String[])groupsMap.get(regs[i]);
changedMap.put(loc,groups);
discoveredMap.put(loc,groups);//replace old loc
discardedMap.remove(loc);
LocatorsUtil.displayLocator(loc,
" locator on groups changed",
Level.FINE);
logger.log(Level.FINE,
" changed member group(s) = "
+GroupsUtil.toCommaSeparatedStr(groups));
} catch(Exception e) { e.printStackTrace(); }
oneChanged = true;
}//end loop
if(oneChanged) {
logger.log(Level.FINE,
" number of currently changed lookup(s) = "
+changedMap.size());
logger.log(Level.FINE,
" number of currently discovered lookup(s) = "
+discoveredMap.size());
}
}//end sync(this)
} else {//(regs == null)
logger.log(Level.FINE, " change event received "
+"-- event.getRegistrars() returned NULL");
}//endif(regs != null)
}//end changed
}//end class GroupChangeListener
/** Thread in which a number of lookup services are started after various
* time delays. This thread is intended to be used by tests that need to
* simulate "late joiner" lookup services. After all of the requested
* lookup services have been started, this thread will exit.
*/
protected class StaggeredStartThread extends Thread {
private final long[] waitTimes
= { 5*1000, 10*1000, 20*1000, 30*1000, 60*1000,
2*60*1000,
60*1000, 30*1000, 20*1000, 10*1000, 5*1000 };
private int startIndx = 0;
private ArrayList locGroupsList;
/** Use this constructor if it is desired that all lookup services
* be started in this thread. The locGroupsList parameter is an
* ArrayList that should contain LocatorGroupsPair instances that
* reference the locator and corresponding member groups of each
* lookup service to start.
*/
public StaggeredStartThread(ArrayList locGroupsList) {
this(0,locGroupsList);
}//end constructor
/** Use this constructor if a number of lookup services (equal to the
* value of the given startIndx) have already been started; and this
* thread will start the remaining lookup services. The locGroupsList
* parameter is an ArrayList that should contain LocatorGroupsPair
* instances that reference the locator and corresponding member
* groups of each lookup service to start.
*/
public StaggeredStartThread(int startIndx,ArrayList locGroupsList) {
super("StaggeredStartThread");
setDaemon(true);
this.startIndx = startIndx;
this.locGroupsList = locGroupsList;
}//end constructor
public void run() {
int n = waitTimes.length;
for(int i=startIndx;((!isInterrupted())&&(i<locGroupsList.size()));
i++)
{
long waitMS = ( i < n ? waitTimes[i] : waitTimes[n-1] );
logger.log(Level.FINE,
" waiting "+(waitMS/1000)+" seconds before "
+"attempting to start the next lookup service");
try {
Thread.sleep(waitMS);
} catch(InterruptedException e) {
/* Need to re-interrupt this thread because catching
* an InterruptedException clears the interrupted status
* of this thread.
*
* If the sleep() call was not interrupted but was timed
* out, this means that this thread should continue
* processing; and the fact that the interrupted status
* has been cleared is consistent with that fact. On the
* other hand, if the sleep() was actually interrupted,
* this means that some entity external to this thread
* is signalling that this thread should exit. But the
* code below that determines whether to exit or continue
* processing bases its decision on the state of the
* interrupted status. And since the interrupted status
* was cleared when the InterruptedException was caught,
* the interrupted status of this thread needs to be reset
* to an interrupted state so that an exit will occur.
*/
Thread.currentThread().interrupt();
}
LocatorGroupsPair pair
= (LocatorGroupsPair)locGroupsList.get(i);
LookupLocator l = pair.locator;
int port = l.getPort();
if(portInUse(port)) port = 0;
if( isInterrupted() ) break;//exit this thread
try {
startLookup(i, port, l.getHost());
} catch(Exception e) {
e.printStackTrace();
}
}//end loop
}//end run
}//end class StaggeredStartThread
/* Protected instance variables */
protected int testType = AUTOMATIC_LOCAL_TEST;
protected String implClassname;
protected int maxSecsEventWait = 10 * 60;
protected int announceInterval = 2 * 60 * 1000;
protected int originalAnnounceInterval = 0;
protected int minNAnnouncements = 2;
protected int nIntervalsToWait = 3;
protected boolean delayLookupStart = false;
protected int nLookupServices = 0;
protected int nAddLookupServices = 0;
protected int nRemoteLookupServices = 0;
protected int nAddRemoteLookupServices = 0;
protected int nServices = 0;//local/serializable test services
protected int nAddServices = 0;//additional local/serializable services
/* Specified jini services */
protected String ldsImplClassname = "no ImplClassname";
protected int nLookupDiscoveryServices = 0;
protected int nAddLookupDiscoveryServices = 0;
protected int nRemoteLookupDiscoveryServices = 0;
protected int nAddRemoteLookupDiscoveryServices = 0;
protected String lrsImplClassname = "no ImplClassname";
protected int nLeaseRenewalServices = 0;
protected int nAddLeaseRenewalServices = 0;
protected int nRemoteLeaseRenewalServices = 0;
protected int nAddRemoteLeaseRenewalServices = 0;
protected String emsImplClassname = "no ImplClassname";
protected int nEventMailboxServices = 0;
protected int nAddEventMailboxServices = 0;
protected int nRemoteEventMailboxServices = 0;
protected int nAddRemoteEventMailboxServices = 0;
/* Attributes per service */
protected int nAttributes = 0;
protected int nAddAttributes = 0;
protected int nSecsLookupDiscovery = 30;
protected int nSecsServiceDiscovery = 30;
protected int nSecsJoin = 30;
protected String remoteHost = "UNKNOWN_HOST";
/* Data structures - lookup services */
protected ArrayList initLookupsToStart = new ArrayList(11);
protected ArrayList addLookupsToStart = new ArrayList(11);
protected ArrayList allLookupsToStart = new ArrayList(11);
protected ArrayList lookupsStarted = new ArrayList(11);
protected ArrayList lookupList = new ArrayList(1);
protected HashMap genMap = new HashMap(11);
protected int nStarted = 0;
/* Data structures - lookup discovery services */
protected ArrayList initLDSToStart = new ArrayList(11);
protected ArrayList addLDSToStart = new ArrayList(11);
protected ArrayList allLDSToStart = new ArrayList(11);
protected ArrayList ldsList = new ArrayList(1);
protected Class[] serviceClasses = null;
protected ArrayList expectedServiceList = new ArrayList(1);
protected QAConfig config = null;
private boolean announcementsStopped = false;
/* Need to keep a local mapping of registrars to their corresponding
* locators and groups so that when a registrar is discarded (indicating
* that a remote call to retrieve the discarded registrar's locator and/or
* group information should not be made), the locator and/or groups can
* be retrieved through a non-remote mechanism. Each time a lookup service
* is started, the registrar and its locator/groups pair are added to this
* map.
*/
protected HashMap regsToLocGroupsMap = new HashMap(11);
/* Private instance variables */
/* Need to keep track of member groups by the index of the corresponding
* lookup service so those groups can be mapped to the correct member
* groups configuration item.
*/
private ArrayList memberGroupsList = new ArrayList(11);
/** Performs actions necessary to prepare for execution of the
* current test as follows:
* <p><ul>
* <li> retrieves configuration values needed by the current test
* <li> retrieves configuration information related to any lookup
* services that may need to be started
* <li> if appropriate, starts the configured number of initial
* lookup services
* </ul>
*/
public void setup(QAConfig config) throws Exception {
super.setup(config);
this.config = config;
logger.log(Level.FINE, " setup()");
debugsync = getConfig().getBooleanConfigVal("qautil.debug.sync",false);
getSetupInfo();
getLookupInfo();
if(!delayLookupStart) {
/* start desired initial lookup services so that they are up
* and running before the test actually begins its execution
*/
startInitLookups();
}//endif
getLDSInfo();
startInitLDS();
}//end setup
/** Cleans up any remaining state not already cleaned up by the test
* itself. If simulated lookup services were used by the test, this
* method stops the multicast generators that were created and
* registered with RMID. This method then performs any standard clean
* up duties performed in the super class.
*/
public void tearDown() {
try {
if(genMap.size() > 0) {
logger.log(Level.FINE,
" tearDown - terminating lookup service(s)");
/* Stop announcements if the generator is simulated, but allow
* the super class' tearDown method to actually destroy the
* lookup services (simulated or non-simulated).
*/
if( !announcementsStopped ) {
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
Object generator = iter.next();
if(generator instanceof DiscoveryProtocolSimulator) {
((DiscoveryProtocolSimulator)generator).stopAnnouncements();
}//endif
}//end loop
announcementsStopped = true;
}//endif(!announcementsStopped)
}//endif
/* Reset original net.jini.discovery.announce property */
if(originalAnnounceInterval == 0) {
Properties props = System.getProperties();
props.remove("net.jini.discovery.announce");
System.setProperties(props);
}
/* Destroy all lookup services registered with activation */
} catch(Exception e) {
e.printStackTrace();
}
super.tearDown();
}//end tearDown
/** With respect to the given objects, determines whether or not the
* following is true: [x.equals(y)] if and only [x == y]
*/
public static boolean satisfiesEqualityTest(Object x, Object y) {
if( (x == null) || (y == null) ) return false;
if( (x == y) && (x.equals(y)) ) return true;
if( !(x == y) && !(x.equals(y)) ) return true;
return false;
}//end satisfiesEqualityTest
/** Returns <code>true</code> if the given arrays are referentially
* equal, or if the given arrays have the same contents;
* <code>false</code> otherwise.
*/
public static boolean arraysEqual(Object[] a0, Object[] a1) {
if(a0 == a1) return true;
if( (a0 == null) || (a1 == null) ) return false;
if(a0.length != a1.length) return false;
iLabel:
for(int i=0;i<a0.length;i++) {
for(int j=0;i<a1.length;j++) {
if( a0[i].equals(a1[j]) ) continue iLabel;//next a0
}//end loop(j)
return false; //a0[i] not contained in a1
}//end loop(i)
return true;
}//end arraysEqual
/** Returns <code>true</code> if the given lists are referentially
* equal, or if the given lists have the same contents;
* <code>false</code> otherwise.
*/
public static boolean listsEqual(List l0, List l1) {
if(l0 == l1) return true;//if both are null it returns true
if( (l0 == null) || (l1 == null) ) return false;
if(l0.size() != l1.size()) return false;
Iterator iter = l0.iterator();
while(iter.hasNext()) {
if( !(l1.contains(iter.next())) ) return false;
}//endif
return true;
}//end listsEqual
/** Returns an array of locators in which each element of the array is
* the locator component of an element of the given <code>ArrayList</code>
* containing instances of <code>LocatorGroupsPair</code>.
*/
public static LookupLocator[] toLocatorArray(ArrayList list) {
LookupLocator[] locArray = new LookupLocator[list.size()];
for(int i=0;i<list.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)list.get(i);
locArray[i] = pair.locator;
}//end loop
return locArray;
}//end toLocatorArray
/** Returns an array of group names in which each element of the
* array is an element of one of the group array component values
* of an element of the given <code>ArrayList</code> containing
* instances of <code>LocatorGroupsPair</code>. That is, the array
* returned contains the union (minus duplicates) of all the group
* names referenced in the given <code>ArrayList</code>.
*
* Note that since the elements of the given <code>ArrayList</code>
* represent the (locator,member groups) pair associated with a lookup
* service, and since a lookup service cannot belong to ALL_GROUPS
* (although it can belong to NO_GROUPS), this method does not deal
* with the possibility of ALL_GROUPS in the given <code>ArrayList</code>.
*/
public static String[] toGroupsArray(ArrayList list) {
ArrayList groupsList = new ArrayList(11);
for(int i=0;i<list.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)list.get(i);
String[] curGroups = pair.groups;
if(curGroups.length == 0) continue;//skip NO_GROUPS
for(int j=0;j<curGroups.length;j++) {
groupsList.add(new String(curGroups[j]));
}//end loop(j)
}//end loop(i)
return ((String[])(groupsList).toArray(new String[groupsList.size()]));
}//end toGroupsArray
/** Convenience method that determines whether the given array
* contains the given object.
*/
public static boolean isElementOf(Object o, Object[] a) {
if((o == null) || (a == null)) return false;
for(int i=0;i<a.length;i++) {
if( o.equals(a[i]) ) return true;
}//end loop
return false;
}//end isElementOf
/** For the given locator of a particular lookup service, if that
* locator is contained in the given set of locators to discover,
* this method returns true; otherwise, it returns false (which
* means that that the corresponding lookup service is not expected
* to be discovered).
*/
public static boolean discoverByLocators
(LookupLocator locator,
LookupLocator[] locatorsToDiscover)
{
return isElementOf(locator,locatorsToDiscover);
}//end discoverByLocators
/** For the given member groups of a particular lookup service,
* if at least one of those member groups is in the given set of
* groups to discover, this method returns true; otherwise, it
* returns false (which means that that the associated lookup
* service is not expected to be discovered).
*/
public static boolean discoverByGroups(String[] memberGroups,
String[] groupsToDiscover)
{
if(groupsToDiscover == DiscoveryGroupManagement.ALL_GROUPS) {
return true;
}//endif
for(int i=0;i<memberGroups.length;i++) {
if(isElementOf(memberGroups[i],groupsToDiscover)) return true;
}//endif
return false;
}//end discoverByGroups
/** Searches the given ArrayList containing instances of
* LocatorGroupsPair for an element that references the given
* locator, and returns the corresponding member groups of the
* lookup service associated with that locator. If no element
* of the given ArrayList references the given locator, then
* null is returned. When null is returned, this should NOT be
* interpretted as ALL_GROUPS since a lookup service cannot be
* a member of ALL_GROUPS; rather, it should be interpretted to
* mean simply that the given locator with corresponding groups
* was not found.
*/
public static String[] getGroups(LookupLocator loc, ArrayList list) {
for(int i=0;i<list.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)list.get(i);
if(loc.equals(pair.locator)) return pair.groups;
}//end loop
return null;
}//end getGroups
/** For each lookup service corresponding to a (locator,groups) pair
* in the given ArrayList, this method determines if at least one
* of that lookup's member groups is in the given set of groups
* to discover; which means that that lookup service is expected
* to be discovered. If all such lookup services are expected to
* be discovered, this method returns true. If at least one lookup
* service belongs to groups which are not desired to be discovered,
* this method returns false.
*/
public static boolean discoverAllLookups(ArrayList list,
String[] groupsToDiscover)
{
/* If ALL_GROUPS, then we must want to discover all the lookups */
if(groupsToDiscover == DiscoveryGroupManagement.ALL_GROUPS) {
return true;
}//endif
/* If at least 1 lookup has member groups that are NOT in the set
* groups to discover, then we do not want to discover all of the
* lookups
*/
for(int i=0;i<list.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)list.get(i);
String[] curMemberGroups = pair.groups;
if( !discoverByGroups(curMemberGroups,groupsToDiscover) ) {
return false;
}//endif
}//end loop
return true;
}//end discoverAllLookups
/** This method returns an array of LocatorGroupsPair instances constructed
* from the elements of the given list of LocatorGroupsPair instances.
* The elements of the return list are selected from the given list
* if one or more of the groups associated with a particular element of
* the given list are contained in the given set of groupsToDiscover.
*/
public static ArrayList filterListByGroups(ArrayList list,
String[] groupsToDiscover)
{
ArrayList filteredList = new ArrayList(list.size());
for(int i=0;i<list.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)list.get(i);
String[] groups = pair.groups;
if(discoverByGroups(groups,groupsToDiscover)) {
filteredList.add(pair);
}//endif
}//end loop
return filteredList;
}//end filterListByGroups
/* Convenience method that returns a set of attributes containing
* one element from the first set, and two copies of each element
* from the second set of attributes. This method is useful for
* constructing attribute sets that can be used in tests that verify
* the behavior of various attribute modification methods.
*/
public static Entry[] addAttrsDup1DupAll(Entry[] attrs0, Entry[] attrs1) {
/* Create an array that contains the first element from attrs0, all
* the elements from attrs1, and then the elements from attrs1 again.
*/
Entry[] tmpAttrs = null;
if(attrs0 != null) {
tmpAttrs = new Entry[1];
tmpAttrs[0] = attrs0[0];
}//endif
return addAttrsWithDups(tmpAttrs,attrs1);
}//end addAttrsDup1DupAll
/* Convenience method that returns a set of attributes containing
* all the elements of the given sets of attributes, with the second
* set of elements duplicated. This method is useful for constructing
* attribute sets that can be used in tests that verify the behavior of
* various attribute modification methods.
*/
public static Entry[] addAttrsWithDups(Entry[] attrs0, Entry[] attrs1) {
/* Create an array that contains elements from attrs0, elements from
* attrs1, and then elements from attrs1 again.
*/
int len0 = ( (attrs0 == null) ? 0 : attrs0.length );
int len1 = ( (attrs1 == null) ? 0 : attrs1.length );
int len = len0+(2*len1);
Entry[] retArray = new Entry[len];
/* Include elements from attrs0 */
int start = 0;
int blockLen = len0;
for(int i=start;i<blockLen;i++) {
retArray[i] = attrs0[i-start];
}//end loop
/* Include elements from attrs1 */
start = blockLen;
blockLen = blockLen+len1;
for(int i=start;i<blockLen;i++) {
retArray[i] = attrs1[i-start];
}//end loop
/* Include elements from attrs1 again */
start = blockLen;
blockLen = blockLen+len1;
for(int i=start;i<blockLen;i++) {
retArray[i] = attrs1[i-start];
}//end loop
return retArray;
}//end addAttrsWithDups
/* Convenience method that returns a set of attributes that contains
* the union of the given sets with duplicates removed.
*/
public static Entry[] addAttrsAndRemoveDups(Entry[] attrs0,Entry[] attrs1){
int len0 = ( (attrs0 == null) ? 0 : attrs0.length );
int len1 = ( (attrs1 == null) ? 0 : attrs1.length );
/* HashSet removes dupliates based on the equals() method */
HashSet sumSet = new HashSet(len0+len1);
for(int i=0;i<len0;i++) {
sumSet.add(attrs0[i]);
}//end loop
for(int i=0;i<len1;i++) {
sumSet.add(attrs1[i]);
}//end loop
return ((Entry[])(sumSet).toArray(new Entry[sumSet.size()]) );
}//end addAttrsAndRemoveDups
/** Convenience method that returns a shallow copy of the
* <code>lookupList</code> <code>ArrayList</code> that contains the
* proxies to the lookup services that have been started so far.
* The size of that list is retrieved while the list is locked,
* so that the list is not modified while the copy is being made.
*/
protected ArrayList getLookupListSnapshot() {
return getLookupListSnapshot(null);
}//end getLookupListSnapshot
protected ArrayList getLookupListSnapshot(String infoStr) {
String str = ( (infoStr == null) ?
" sync on lookupList --> " :
" "+infoStr+" - sync on lookupList --> ");
if(debugsync) logger.log(Level.FINE, str+"requested");
synchronized(lookupList) {
if(debugsync) logger.log(Level.FINE, str+"granted");
ArrayList listSnapshot = new ArrayList(lookupList.size());
for(int i=0;i<lookupList.size();i++) {
listSnapshot.add(i,lookupList.get(i));
}//end loop
if(debugsync) logger.log(Level.FINE, str+"released");
return listSnapshot;
}//end sync(lookupList)
}//end getLookupListSnapshot
/** Convenience method that returns the current size of the
* <code>lookupList</code> <code>ArrayList</code> that contains the
* proxies to the lookup services that have been started so far.
* The size of that list is retrieved while the list is locked,
* so that the list is not modified while the retrieval is being made.
*/
protected int curLookupListSize() {
return curLookupListSize(null);
}//end curLookupListSize
protected int curLookupListSize(String infoStr) {
String str = ( (infoStr == null) ?
" sync on lookupList --> " :
" "+infoStr+" - sync on lookupList --> ");
if(debugsync) logger.log(Level.FINE, str+"requested");
synchronized(lookupList) {
if(debugsync) logger.log(Level.FINE, str+"granted");
int size = lookupList.size();
if(debugsync) logger.log(Level.FINE, str+"released");
return size;
}//end sync(lookupList)
}//end curLookupListSize
/* Convenience method that removes the duplicate elements from the
* given set or attributes and returns the result.
*/
public static Entry[] removeDups(Entry[] attrs) {
int len = ( (attrs == null) ? 0 : attrs.length );
/* HashSet removes dupliates based on the equals() method */
HashSet attrsSet = new HashSet(len);
for(int i=0;i<len;i++) {
attrsSet.add(attrs[i]);
}//end loop
return ((Entry[])(attrsSet).toArray(new Entry[attrsSet.size()]) );
}//end addAttrsAndRemoveDups
/** Method that compares the given port to the ports of all the lookup
* services that have been currently started. Returns <code>true</code>
* if the given port equals any of the ports referenced in the set
* lookup services that have been started; <code>false</code>
* otherwise. This method is useful for guaranteeing unique port
* numbers when starting lookup services.
*/
protected boolean portInUse(int port) {
for(int i=0;i<lookupsStarted.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)lookupsStarted.get(i);
int curPort = (pair.locator).getPort();
if(port == curPort) return true;
}//end loop
return false;
}//end portInUse
/** Constructs a <code>LookupLocator</code> using configuration information
* corresponding to the value of the given parameter <code>indx</code>.
* Useful when lookup services need to be started, or simply when
* instances of <code>LookupLocator</code> need to be constructed with
* meaningful state.
*/
protected LookupLocator getTestLocator(int indx) throws TestException {
/* Locator for lookup service corresponding to indx */
int port = getConfig().getServiceIntProperty
("net.jini.core.lookup.ServiceRegistrar",
"port", indx);
if (port == Integer.MIN_VALUE) {
port = 4160;
}
String hostname =
config.getServiceHost("net.jini.core.lookup.ServiceRegistrar", indx, null);
logger.log(Level.FINER, "getServiceHost returned " + hostname);
if (hostname == null) {
hostname = "localhost";
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch(UnknownHostException e) {
e.printStackTrace();
}
}
return QAConfig.getConstrainedLocator(hostname,port);
}//end getTestLocator
/** Constructs a <code>LookupLocator</code> using configuration information
* corresponding to the value of the given parameter <code>indx</code>.
* Useful when lookup services need to be started, or simply when
* instances of <code>LookupLocator</code> need to be constructed with
* meaningful state.
*/
protected LookupLocator getRemoteTestLocator(int indx) {
/* Locator for lookup service corresponding to indx */
int port = getConfig().getServiceIntProperty
("net.jini.core.lookup.ServiceRegistrar",
"port", indx);
if (port == Integer.MIN_VALUE) {
port = 4160;
}
// used for book keeping only, so don't need a constrainable locator
return QAConfig.getConstrainedLocator(remoteHost,port);
}//end getRemoteTestLocator
/** Convenience method that can be used to start, at a single point
* during the current test run, all of the lookup services needed by
* that test run. Useful when all of the lookup services are to be
* started during setup processing.
*/
protected void startAllLookups() throws Exception {
startInitLookups();
startAddLookups();
}//end startAllLookups
/** Convenience method that can be used to start, at a single point
* during the current test run, all of the lookup services INITIALLY
* needed by that test run. Useful when an initial set of lookups are
* to be started during setup processing, and (possibly) an additional
* set of lookups are to be started at some later time, after the test
* has already begun execution.
*/
protected void startInitLookups() throws Exception {
if(nLookupServices > 0) {
/* Skip over remote lookups to the indices of the local lookups */
int n0 = nRemoteLookupServices + nAddRemoteLookupServices;
int n1 = n0 + nLookupServices;
for(int i=n0;i<n1;i++) {
LocatorGroupsPair pair
= (LocatorGroupsPair)initLookupsToStart.get(i);
int port = (pair.locator).getPort();
if(portInUse(port)) port = 0;
String hostname = startLookup(i,port, pair.locator.getHost());
logger.log(Level.FINEST,
"service host is '" + hostname
+ "', this host is '" + config.getLocalHostName() + "'");
if(port == 0) {
Object locGroupsPair = lookupsStarted.get(i);
initLookupsToStart.set(i,locGroupsPair);
allLookupsToStart.set(i,locGroupsPair);
}
LocatorGroupsPair p = (LocatorGroupsPair) initLookupsToStart.get(i);
LookupLocator l = p.locator;
logger.log(Level.FINEST, "init locator " + i + " = " + l);
}//end loop
if(testType != MANUAL_TEST_LOCAL_COMPONENT) {
if(!listsEqual(initLookupsToStart,lookupsStarted)) {
logger.log(Level.FINE,
" initial lookups started != "
+"initial lookups wanted");
logger.log(Level.FINE,
" initial lookups started --");
displayLookupStartInfo(lookupsStarted);
logger.log(Level.FINE,
" initial lookups wanted --");
displayLookupStartInfo(initLookupsToStart);
tearDown();
throw new TestException("initial lookups started != "
+"initial lookups wanted");
}//endif
}//endif
}//endif(nLookupServices > 0)
}//end startInitLookups
/** Convenience method that can be used to start, at a single point
* during the current test run, any additional lookup services
* needed by that test run. Useful when an initial set of lookups are
* to be started during setup processing, and an additional set of
* lookups are to be started at some later time, after the test
* has already begun execution.
*/
protected void startAddLookups() throws Exception {
if(nAddLookupServices > 0) {
/* Skip over remote lookups and lookups already started to the
* indices of the additional local lookups
*/
int n0 = nRemoteLookupServices + nAddRemoteLookupServices
+ lookupsStarted.size();
int n1 = n0 + nAddLookupServices;
for(int i=n0;i<n1;i++) {
int j = i-n0;
LocatorGroupsPair pair
= (LocatorGroupsPair)addLookupsToStart.get(j);
int port = (pair.locator).getPort();
if(portInUse(port)) port = 0;
String hostname = startLookup(i,port, pair.locator.getHost());
if(port == 0) {
Object locGroupsPair = lookupsStarted.get(i);
addLookupsToStart.set(j,locGroupsPair);
allLookupsToStart.set(i,locGroupsPair);
}
LocatorGroupsPair p = (LocatorGroupsPair) addLookupsToStart.get(j);
LookupLocator l = p.locator;
logger.log(Level.FINEST, "add locator " + j + " = " + l);
}//end loop
if(testType != MANUAL_TEST_LOCAL_COMPONENT) {
if(!listsEqual(allLookupsToStart,lookupsStarted)) {
logger.log(Level.FINE,
" additional lookups started != "
+"additional lookups wanted");
logger.log(Level.FINE,
" additional lookups started --");
displayLookupStartInfo(lookupsStarted);
logger.log(Level.FINE,
" additional lookups wanted --");
displayLookupStartInfo(allLookupsToStart);
tearDown();
throw new TestException("additional lookups started != "
+"additional lookups wanted");
}//endif
}//endif
}//endif(nAddLookupServices > 0)
}//end startAddLookups
/**
* Start a lookup service with configuration referenced by the
* given parameter values.
*
* @param indx the index of lookup services within the set of
* lookups to start for this test
* @param port the port the lookup service is to use
* @return the name of the system the lookup service was started on
* @throws Exception if something goes wrong
*/
protected String startLookup(int indx, int port) throws Exception {
return startLookup(indx, port, config.getLocalHostName());
}
protected String startLookup(int indx, int port, String serviceHost) throws Exception {
logger.log(Level.FINE, " starting lookup service "+indx);
/* retrieve the member groups with which to configure the lookup */
String[] memberGroups = (String[])memberGroupsList.get(indx);
ServiceRegistrar lookupProxy = null;
String simulatorName =
"com.sun.jini.test.services.lookupsimulator.LookupSimulatorImpl";
if(implClassname.equals(simulatorName)) {
DiscoveryProtocolSimulator generator = null;
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> requested");
synchronized(lookupList) {
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> granted");
/* Use either a random or an explicit locator port */
generator = new DiscoveryProtocolSimulator
(config,memberGroups,manager, port);
genMap.put( generator, memberGroups );
lookupProxy = generator.getLookupProxy();
lookupList.add( lookupProxy );
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+" added new proxy to lookupList");
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> released");
}//end sync(lookupList)
/* Force non-unique groups for manual tests */
if( (testType == MANUAL_TEST_REMOTE_COMPONENT)
|| (testType == MANUAL_TEST_LOCAL_COMPONENT) )
{
generator.setMemberGroups(memberGroups);
}//endif
} else {//start a non-simulated lookup service implementation
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> requested");
synchronized(lookupList) {
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> granted");
/* returned proxy is already prepared */
lookupProxy = manager.startLookupService(serviceHost);
lookupList.add( lookupProxy );
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+" added new proxy to lookupList");
if(debugsync) logger.log(Level.FINE,
" BaseQATest.startLookup - "
+"sync on lookupList --> released");
}//end sync(lookupList)
genMap.put( lookupProxy, memberGroups );
/* Force non-unique groups for manual tests */
if( (testType == MANUAL_TEST_REMOTE_COMPONENT)
|| (testType == MANUAL_TEST_LOCAL_COMPONENT) )
{
if(lookupProxy instanceof Administrable) {
Object admin = ((Administrable)lookupProxy).getAdmin();
admin = getConfig().prepare("test.reggieAdminPreparer",
admin);
if(admin instanceof DiscoveryAdmin) {
((DiscoveryAdmin)admin).setMemberGroups(memberGroups);
}
}
}
}
LookupLocator lookupLocator =
QAConfig.getConstrainedLocator(lookupProxy.getLocator());
LocatorGroupsPair locGroupsPair = new LocatorGroupsPair(lookupLocator,
memberGroups);
try {
lookupsStarted.add(indx,locGroupsPair);
} catch(IndexOutOfBoundsException e) {
/* There must be remote lookups, simply add it without the index */
lookupsStarted.add(locGroupsPair);
}
regsToLocGroupsMap.put(lookupProxy,locGroupsPair);
LocatorsUtil.displayLocator(lookupLocator,
" locator",Level.FINE);
logger.log(Level.FINE, " memberGroup(s) = "
+GroupsUtil.toCommaSeparatedStr(memberGroups));
nStarted = genMap.size();
return serviceHost;
}
/** Common code shared by each test that needs to wait for discovered
* events from the discovery helper utility, and verify that the
* expected discovered events have indeed arrived.
*/
protected void waitForDiscovery(LookupListener listener)
throws TestException
{
/* Wait for the expected # of discovered events from the listener */
int nSecsToWait0 = nIntervalsToWait*fastTimeout;
if(nSecsToWait0 == 0) nSecsToWait0 = fastTimeout;//default value
int nSecsToWait1 = 1; // guarantee at least 1 pass through timer loop
if(nSecsToWait0 < maxSecsEventWait) {
nSecsToWait1 = (maxSecsEventWait - nSecsToWait0);
}//endif
if(useFastTimeout) {//reset timeouts for faster completion
nSecsToWait0 = fastTimeout;
nSecsToWait1 = fastTimeout;
maxSecsEventWait = fastTimeout;
}//endif
logger.log(Level.FINE, " for DISCOVERY events -- waiting "
+"at least "+nSecsToWait0+" seconds, but no more "
+"than "+(nSecsToWait0+nSecsToWait1)+" seconds ...");
/* no early breakout; verifies no extra discovered events are sent */
for(int i=0;i<nSecsToWait0;i++) {
DiscoveryServiceUtil.delayMS(1000);
}//end loop
/* Minimum wait period complete, now test for discovered events. Wait
* no more than (max-min) seconds, exit immediately on success.
*/
logger.log(Level.FINE, " initial wait period complete ... "
+"waiting at most "+nSecsToWait1+" more seconds ...");
boolean discoveryComplete = false;
boolean showCompInfo = true;//turn this off after 1st pass thru loop
Map discoveredClone = null;
iLoop:
for(int i=0;i<nSecsToWait1;i++) {
synchronized(listener) {
Map discoveredMap = listener.discoveredMap;
Map expectedDiscoveredMap = listener.expectedDiscoveredMap;
if(displayOn &&
(discoveredClone == null
|| !locGroupsMapsEqual(discoveredMap, discoveredClone)))
{
discoveredClone = (Map) ((HashMap)discoveredMap).clone();
logger.log(Level.FINE,
" discoveredMap.size == "
+discoveredMap.size());
Set eSet = discoveredMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" discoveredMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" discoveredMap.groups == NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" discoveredMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
logger.log(Level.FINE,
" expectedDiscoveredMap.size == "
+expectedDiscoveredMap.size());
eSet = expectedDiscoveredMap.entrySet();
iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" expectedDiscoveredMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" expectedDiscoveredMap.groups == "
+"NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" expectedDiscoveredMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
}//endif(displayOn)
/* nEventsReceived == nEventsExpected for this listener? */
if(discoveredMap.size() == expectedDiscoveredMap.size()) {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedDiscoveredMap.size()+") == events "
+"received ("+discoveredMap.size()+")");
}//endif
/* locators in received event == expected locators? */
if( locGroupsMapsEqual(expectedDiscoveredMap,discoveredMap,
showCompInfo) )
{
logger.log(Level.FINE,
" events expected ("
+expectedDiscoveredMap.size()+") == events "
+"received ("+discoveredMap.size()+"),"
+" all locators equal");
discoveryComplete = true;
break iLoop;
} else {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" not all lookups equal");
}//endif
}//endif
} else {//(nEventsReceived != nEventsExpected)
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedDiscoveredMap.size()
+") != events received ("
+discoveredMap.size()+")");
}//endif
}//endif(nEventsReceived == nEventsExpected)
}//end sync(listener)
DiscoveryServiceUtil.delayMS(1000);
showCompInfo = false;//display comparison info only when i = 0
}//end loop(iLoop)
logger.log(Level.FINE, " DISCOVERY wait period complete");
synchronized(listener) {
if(!discoveryComplete) {
throw new TestException("discovery failed -- "
+"waited "+nSecsToWait1
+" seconds ("+(nSecsToWait1/60)
+" minutes) -- "
+listener.expectedDiscoveredMap.size()
+" discovery event(s) expected, "
+listener.discoveredMap.size()
+" discovery event(s) received");
}//endif(!discoveryComplete)
logger.log(Level.FINE, " "
+listener.expectedDiscoveredMap.size()
+" discovery event(s) expected, "
+listener.discoveredMap.size()
+" discovery event(s) received");
}//end sync(listener)
}//end waitForDiscovery
/** Common code shared by each test that needs to wait for discarded
* events from the discovery helper utility, and verify that the
* expected discarded events have indeed arrived.
*/
protected void waitForDiscard(LookupListener listener)
throws TestException
{
/* Wait for the expected # of discard events from the listener */
int nSecsToWait0 = nIntervalsToWait*fastTimeout;
if(nSecsToWait0 == 0) nSecsToWait0 = fastTimeout;//default value
int nSecsToWait1 = 1; // guarantee at least 1 pass through timer loop
if(nSecsToWait0 < maxSecsEventWait) {
nSecsToWait1 = (maxSecsEventWait - nSecsToWait0);
}//endif
if(useFastTimeout) {//reset timeouts for faster completion
nSecsToWait0 = fastTimeout;
nSecsToWait1 = fastTimeout;
maxSecsEventWait = fastTimeout;
}//endif
logger.log(Level.FINE, " for DISCARD events -- waiting "
+"at least "+nSecsToWait0+" seconds, but no more "
+"than "+(nSecsToWait0+nSecsToWait1)+" seconds ...");
/* no early breakout; verifies no extra discard events are sent */
for(int i=0;i<nSecsToWait0;i++) {
DiscoveryServiceUtil.delayMS(1000);
}//end loop
/* Minimum wait period complete, now test for discard events. Wait
* no more than (max-min) seconds, exit immediately on success.
*/
logger.log(Level.FINE, " initial wait period complete ... "
+"waiting at most "+nSecsToWait1+" more seconds ...");
boolean discardComplete = false;
boolean showCompInfo = true;//turn this off after 1st pass thru loop
Map discardedClone = null;
iLoop:
for(int i=0;i<nSecsToWait1;i++) {
synchronized(listener) {
Map discardedMap = listener.discardedMap;
Map expectedDiscardedMap = listener.expectedDiscardedMap;
if(displayOn &&
(discardedClone == null
|| !locGroupsMapsEqual(discardedMap, discardedClone)))
{
discardedClone = (Map) ((HashMap)discardedMap).clone();
logger.log(Level.FINE,
" discardedMap.size == "
+discardedMap.size());
Set eSet = discardedMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" discardedMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" discardedMap.groups == NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" discardedMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
logger.log(Level.FINE,
" expectedDiscardedMap.size == "
+expectedDiscardedMap.size());
eSet = expectedDiscardedMap.entrySet();
iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" expectedDiscardedMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" expectedDiscardedMap.groups == "
+"NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" expectedDiscardedMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
}//endif(displayOn)
/* nEventsReceived == nEventsExpected for this listener? */
if(discardedMap.size() == expectedDiscardedMap.size()) {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedDiscardedMap.size()+") == events "
+"received ("+discardedMap.size()+")");
}//endif
/* locators in received event == expected locators? */
if( locGroupsMapsEqual(expectedDiscardedMap,discardedMap,
showCompInfo) )
{
logger.log(Level.FINE,
" events expected ("
+expectedDiscardedMap.size()+") == events "
+"received ("+discardedMap.size()+"),"
+" all locators equal");
discardComplete = true;
break iLoop;
} else {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" not all lookups equal");
}//endif
}//endif
} else {//(nEventsReceived != nEventsExpected)
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedDiscardedMap.size()
+") != events received ("
+discardedMap.size()+")");
}//endif
}//endif(nEventsReceived == nEventsExpected)
}//end sync(listener)
DiscoveryServiceUtil.delayMS(1000);
showCompInfo = false;//display comparison info only when i = 0
}//end loop(iLoop)
logger.log(Level.FINE, " DISCARD wait period complete");
synchronized(listener) {
if(!discardComplete) {
throw new TestException("discard failed -- "
+"waited "+nSecsToWait1
+" seconds ("+(nSecsToWait1/60)
+" minutes) -- "
+listener.expectedDiscardedMap.size()
+" discard event(s) expected, "
+listener.discardedMap.size()
+" discard event(s) received");
}//endif(!discardComplete)
logger.log(Level.FINE, " "
+listener.expectedDiscardedMap.size()
+" discard event(s) expected, "
+listener.discardedMap.size()
+" discard event(s) received");
}//end sync(listener)
}//end waitForDiscard
/** Common code shared by each test that needs to wait for changed
* events from the discovery helper utility, and verify that the
* expected changed events have indeed arrived.
*/
protected void waitForChange(GroupChangeListener listener)
throws TestException
{
/* Wait for the expected # of changed events from the listener */
int nSecsToWait0 = nIntervalsToWait*fastTimeout;
if(nSecsToWait0 == 0) nSecsToWait0 = fastTimeout;//default value
int nSecsToWait1 = 1; // guarantee at least 1 pass through timer loop
if(nSecsToWait0 < maxSecsEventWait) {
nSecsToWait1 = (maxSecsEventWait - nSecsToWait0);
}//endif
if(useFastTimeout) {//reset timeouts for faster completion
nSecsToWait0 = fastTimeout;
nSecsToWait1 = fastTimeout;
maxSecsEventWait = fastTimeout;
}//endif
logger.log(Level.FINE, " for CHANGE events -- waiting "
+"at least "+nSecsToWait0+" seconds, but no more "
+"than "+(nSecsToWait0+nSecsToWait1)+" seconds ...");
/* no early breakout; verifies no extra changed events are sent */
for(int i=0;i<nSecsToWait0;i++) {
DiscoveryServiceUtil.delayMS(1000);
}//end loop
/* Minimum wait period complete, now test for changed events. Wait
* no more than (max-min) seconds, exit immediately on success.
*/
logger.log(Level.FINE, " initial wait period complete ... "
+"waiting at most "+nSecsToWait1+" more seconds ...");
boolean changeComplete = false;
boolean showCompInfo = true;//turn this off after 1st pass thru loop
Map changedClone = null;
iLoop:
for(int i=0;i<nSecsToWait1;i++) {
synchronized(listener) {
Map changedMap = listener.changedMap;
Map expectedChangedMap = listener.expectedChangedMap;
if(displayOn &&
(changedClone == null
|| !locGroupsMapsEqual(changedMap, changedClone)))
{
changedClone = (Map) ((HashMap)changedMap).clone();
logger.log(Level.FINE,
" changedMap.size == "
+changedMap.size());
Set eSet = changedMap.entrySet();
Iterator iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" changedMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" changedMap.groups == NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" changedMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
logger.log(Level.FINE,
" expectedChangedMap.size == "
+expectedChangedMap.size());
eSet = expectedChangedMap.entrySet();
iter = eSet.iterator();
while(iter.hasNext()) {
Map.Entry pair = (Map.Entry)iter.next();
LookupLocator loc = (LookupLocator)pair.getKey();
String[] groups = (String[])pair.getValue();
logger.log(Level.FINE,
" expectedChangedMap.locator = "+loc);
if( groups.length <= 0 ) {
logger.log(Level.FINE,
" expectedChangedMap.groups == "
+"NO_GROUPS");
} else {
for(int m=0;m<groups.length;m++){
logger.log(Level.FINE,
" expectedChangedMap.groups["
+m+"] == "+groups[m]);
}//end loop
}//endif
}//end loop
}//endif(displayOn)
/* nEventsReceived == nEventsExpected for this listener? */
if(changedMap.size() == expectedChangedMap.size()) {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedChangedMap.size()+") == events "
+"received ("+changedMap.size()+")");
}//endif
/* locators in received event == expected locators? */
if( locGroupsMapsEqual(expectedChangedMap,changedMap,
showCompInfo) )
{
logger.log(Level.FINE,
" events expected ("
+expectedChangedMap.size()+") == events "
+"received ("+changedMap.size()+"),"
+" all locators equal");
changeComplete = true;
break iLoop;
} else {
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" not all lookups equal");
}//endif
}//endif
} else {//(nEventsReceived != nEventsExpected)
if(i == (nSecsToWait1-1)) {
logger.log(Level.FINE,
" events expected ("
+expectedChangedMap.size()
+") != events received ("
+changedMap.size()+")");
}//endif
}//endif(nEventsReceived == nEventsExpected)
}//end sync(listener)
DiscoveryServiceUtil.delayMS(1000);
showCompInfo = false;//display comparison info only when i = 0
}//end loop(iLoop)
logger.log(Level.FINE, " CHANGE wait period complete");
synchronized(listener) {
if(!changeComplete) {
throw new TestException("change failed -- "
+"waited "+nSecsToWait1
+" seconds ("+(nSecsToWait1/60)
+" minutes) -- "
+listener.expectedChangedMap.size()
+" change event(s) expected, "
+listener.changedMap.size()
+" change event(s) received");
}//endif(!changeComplete)
logger.log(Level.FINE, " "
+listener.expectedChangedMap.size()
+" change event(s) expected, "
+listener.changedMap.size()
+" change event(s) received");
}//end sync(listener)
}//end waitForChange
/** Given two locator-to-groups mappings, this method compares both
* the locator key sets and the groups value sets, and returns
* <code>true</code> if the elements of the key sets and the value sets
* are found to be equal; returns <code>false</code> otherwise.
*/
protected boolean locGroupsMapsEqual( Map map0, Map map1 ) {
if(!locGroupsMapsEqualByLoc(map0,map1,false)) return false;
return locGroupsMapsEqualByGroups(map0,map1,false);
}//end locGroupsMapsEqual
/** Given two locator-to-groups mappings, this method compares both
* the locator key sets and the groups value sets, displaying the
* locator and group information in each map if the <code>displayOn</code>
* parameter is <code>true</code>. This method returns <code>true</code>
* if the elements of the key sets and the value sets are found to be
* equal; returns <code>false</code> otherwise.
*/
protected boolean locGroupsMapsEqual( Map map0, Map map1,
boolean displayOn)
{
if(!locGroupsMapsEqualByLoc(map0,map1,displayOn)) return false;
return locGroupsMapsEqualByGroups(map0,map1,displayOn);
}//end locGroupsMapsEqual
/** Given two locator-to-groups mappings, this method compares the
* elements of the locator key sets, and returns <code>true</code>
* if the locators in the key sets are found to be equal; returns
* <code>false</code> otherwise.
*/
protected boolean locGroupsMapsEqualByLoc( Map map0, Map map1 ) {
return locGroupsMapsEqualByLoc(map0,map1,false);
}//end locGroupsMapsEqualByLoc
/** Given two locator-to-groups mappings, this method compares the
* elements of the locator key sets, displaying the locator
* information in given map if the <code>displayOn</code> parameter
* is <code>true</code>. This method returns <code>true</code>
* if the locators in the key sets are found to be equal; returns
* <code>false</code> otherwise.
*/
protected boolean locGroupsMapsEqualByLoc( Map map0, Map map1,
boolean displayOn )
{
if( (map0 == null) || (map1 == null) ) return false;
if(map0.size() != map1.size()) return false;
Collection locKeys0 = map0.keySet();
Collection locKeys1 = map1.keySet();
if(displayOn) {
logger.log(Level.FINE, " comparing locators ... ");
logger.log(Level.FINE, " locators set 0 -- ");
}//endif
LookupLocator[] locs0 = new LookupLocator[locKeys0.size()];
Iterator iter = locKeys0.iterator();
for(int i=0;iter.hasNext();i++) {
locs0[i] = (LookupLocator)iter.next();
if(displayOn) logger.log(Level.FINE, " "+locs0[i]);
}//end loop
if(displayOn) logger.log(Level.FINE, " locators set 1 -- ");
LookupLocator[] locs1 = new LookupLocator[locKeys1.size()];
iter = locKeys1.iterator();
for(int i=0;iter.hasNext();i++) {
locs1[i] = (LookupLocator)iter.next();
if(displayOn) logger.log(Level.FINE, " "+locs1[i]);
}//end loop
return LocatorsUtil.compareLocatorSets(locs0,locs1, Level.OFF);
}//end locGroupsMapsEqualByLoc
/** Given two locator-to-groups mappings, this method compares the
* elements of the value sets which contain arrays of member groups.
* This method returns <code>true</code> if the group sets in those
* value sets are found to be equal; returns <code>false</code>
* otherwise.
*/
protected boolean locGroupsMapsEqualByGroups( Map map0, Map map1 ) {
return locGroupsMapsEqualByGroups(map0,map1,false);
}//end locGroupsMapsEqualByGroups
/** Given two locator-to-groups mappings, this method compares the
* elements of the value sets which contain arrays of member groups,
* displaying the locator and group information in each map if
* the <code>displayOn</code> parameter is <code>true</code>.
* This method returns <code>true</code> if the group sets in those
* value sets are found to be equal; returns <code>false</code>
* otherwise.
*/
protected boolean locGroupsMapsEqualByGroups( Map map0, Map map1,
boolean displayOn )
{
if( (map0 == null) || (map1 == null) ) return false;
if(map0.size() != map1.size()) return false;
Collection locKeys0 = map0.keySet();
if(displayOn) {
logger.log(Level.FINE,
" comparing group sets of each lookup ... ");
}//endif
Iterator iter = locKeys0.iterator();
for(int i=0;iter.hasNext();i++) {
LookupLocator loc = (LookupLocator)iter.next();
String[] groups0 = (String[])map0.get(loc);
String[] groups1 = (String[])map1.get(loc);
if(displayOn) {
logger.log(Level.FINE,
" set 0 -- locator = "+loc);
if(groups0.length == 0) {
logger.log(Level.FINE,
" groups = NO_GROUPS");
} else {
for(int j=0;j<groups0.length;j++) {
logger.log(Level.FINE,
" group["+j+"] = "+groups0[j]);
}//end loop
}//endif
logger.log(Level.FINE,
" set 1 -- locator = "+loc);
if(groups1.length == 0) {
logger.log(Level.FINE,
" groups = NO_GROUPS");
} else {
for(int j=0;j<groups1.length;j++) {
logger.log(Level.FINE,
" group["+j+"] = "+groups1[j]);
}//end loop
}//endif
}//endif(displayOn)
if(!GroupsUtil.compareGroupSets(groups0,groups1, Level.OFF)) return false;
}//end loop
return true;
}//end locGroupsMapsEqualByGroups
/** Returns the proxy to each lookup service started (already prepared)*/
protected ServiceRegistrar[] getLookupProxies() {
ServiceRegistrar[] proxies = new ServiceRegistrar[genMap.size()];
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
Object curObj = iter.next();
if(curObj instanceof DiscoveryProtocolSimulator) {
proxies[i]
= ((DiscoveryProtocolSimulator)curObj).getLookupProxy();
} else {
proxies[i] = (ServiceRegistrar)curObj;
}//endif
}//end loop
return proxies;
}//end getLookupProxies
/** For each lookup service corresponding to an element of the global
* HashMap 'genMap', this method stops the generation of multicast
* announcements by either destroying the lookup service, or
* explicitly stopping the announcements and then destroying the
* lookup service.
*
* @throws com.sun.jini.qa.harness.TestException
*/
protected void terminateAllLookups() throws TestException {
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
Object curObj = iter.next();
ServiceRegistrar regProxy = null;
if(curObj instanceof DiscoveryProtocolSimulator) {
DiscoveryProtocolSimulator curGen
= (DiscoveryProtocolSimulator)curObj;
regProxy = curGen.getLookupProxy();
curGen.stopAnnouncements();
} else {
regProxy = (ServiceRegistrar)curObj;
}//endif
/* destroy lookup service i */
manager.destroyService(regProxy);
}//end loop
announcementsStopped = true;
}//end terminateAllLookups
/** This method stops the generation of multicast announcements from each
* lookup service that has been started. The announcements are stopped
* directly if possible or, if stopping the announcements directly is not
* possible, the announcements are stopped indirectly by destroying each
* lookup service (ex. reggie does not allow one to stop its multicast
* announcements while allowing the service to remain running and
* reachable.)
*/
protected void stopAnnouncements() {
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
logger.log(Level.FINE, " stop multicast announcements "
+"from lookup service "+i+" ...");
Object curObj = iter.next();
if(curObj instanceof DiscoveryProtocolSimulator) {
DiscoveryProtocolSimulator curGen
= (DiscoveryProtocolSimulator)curObj;
curGen.stopAnnouncements();
} else {//cannot stop the announcements, must destroy the lookup
/* It's not a simulated LUS, thus the only way to stop the
* announcements is to destroy each LUS individually.
*/
manager.destroyService((ServiceRegistrar)curObj);
}//endif
}//end loop
announcementsStopped = true;
}//end stopAnnouncements
/** For each lookup service proxy contained in the input array, this
* method first determines if that lookup service is reachable by
* attempting to retrieve the associated locator; that is, it
* attempts to 'ping' the lookup service. The lookup services found
* to be un-reachable are then used to update the given listener's
* expected discard state. After updating the listener's expected
* state, each unreachable lookup service is discarded from the given
* instance of LookupDiscovery.
*
* This method returns an ArrayList containing LocatorGroupsPair
* instances corresponding to the lookups that were NOT discarded.
* This is so that the expected discard event state can be built
* correctly (a discarded event should not be expected for a lookup
* service that couldn't be discarded).
*/
protected ArrayList pingAndDiscard(ServiceRegistrar[] proxies,
DiscoveryManagement dm,
LookupListener listener)
{
ArrayList proxiesToDiscard = new ArrayList(1);
ArrayList locGroupsNotDiscarded = new ArrayList(1);
/* Determine proxies to discard and proxies that cannot be discarded */
for(int i=0;i<proxies.length;i++) {
LocatorGroupsPair curPair
= (LocatorGroupsPair)regsToLocGroupsMap.get(proxies[i]);
try {
LookupLocator loc = QAConfig.getConstrainedLocator(proxies[i].getLocator());
logger.log(Level.FINE, " ");
if(curPair != null) {
logger.log(Level.FINE,
" warning -- lookup service "
+"is still reachable --> locator = "
+curPair.locator+"\n");
locGroupsNotDiscarded.add(curPair);
} else {
logger.log(Level.FINE,
" warning -- lookup service "+i
+" is still reachable\n");
}//endif
} catch(RemoteException e) {//lookup is un-reachable, discard it
proxiesToDiscard.add(proxies[i]);
}
}//end loop
/* Perform the actual discards to generate the discard events */
for(int i=0;i<proxiesToDiscard.size();i++) {
dm.discard((ServiceRegistrar)proxiesToDiscard.get(i));
}//end loop
return locGroupsNotDiscarded;//return proxies we couldn't discard
}//end pingAndDiscard
/** Since the lookup discovery utility typically sends a unicast
* announcement at startup, resulting in immediate discovery by
* unicast, the lookup service which generates the multicast
* announcements won't send its first announcement until after
* net.jini.discovery.announce number of milliseconds. This means
* that until that first multicast announcement arrives, the lookup
* discovery utility will have no point of reference (no initial time
* stamp) with which to determine if the announcements have indeed
* stopped. Thus, multicast monitoring doesn't really begin until after
* the first announcement arrives. It is for this reason that before
* the multicast announcements are stopped, it may be of value to wait
* enough time so as to guarantee that at least one announcement has
* been sent. This method can be used by tests that wish to provide
* such a guarantee.
*
* The time this method waits is computed from the configurable number
* of announcement time intervals over which to wait (nIntervalsToWait),
* and the configurable minimum number of announcements over which
* unreachability is determined (minNAnnouncements).
*
* Note that this method should only be used when the test uses
* simulated lookup services.
*/
protected void verifyAnnouncementsSent() {
logger.log(Level.FINE,
" number of announcements to wait for -- "
+minNAnnouncements);
logger.log(Level.FINE,
" number of intervals to wait through -- "
+nIntervalsToWait);
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
DiscoveryProtocolSimulator curGen =
(DiscoveryProtocolSimulator)iter.next();
logger.log(Level.FINE,
" gen "+i
+" - waiting ... announcements so far -- "
+curGen.getNAnnouncementsSent());
for(int j=0; ((j<nIntervalsToWait)
&&(curGen.getNAnnouncementsSent()< minNAnnouncements));j++)
{
DiscoveryServiceUtil.delayMS(announceInterval);
logger.log(Level.FINE,
" gen "+i
+" - waiting ... announcements so far -- "
+curGen.getNAnnouncementsSent());
}//end loop
logger.log(Level.FINE,
" gen "+i
+" - wait complete ... announcements -- "
+curGen.getNAnnouncementsSent());
}//end loop
}//end verifyAnnouncementsSent
/** This method replaces, with the given set of groups, the current
* member groups of the given lookup service (<code>generator</code>).
* This method returns an instance of <code>LocatorGroupsPair</code> in
* which the locator of the given lookup service is paired with the given
* set of new groups.
*/
protected LocatorGroupsPair replaceMemberGroups(Object generator,
String[] newGroups)
throws RemoteException
{
ServiceRegistrar regProxy = null;
if(generator instanceof DiscoveryProtocolSimulator) {
regProxy
= ((DiscoveryProtocolSimulator)generator).getLookupProxy();
((DiscoveryProtocolSimulator)generator).setMemberGroups(newGroups);
} else {
regProxy = (ServiceRegistrar)generator;
DiscoveryAdmin admin
= (DiscoveryAdmin)( ((Administrable)regProxy).getAdmin() );
try {
admin = (DiscoveryAdmin)
getConfig().prepare("test.reggieAdminPreparer", admin);
} catch (TestException e) {
throw new RemoteException("Problem preparing admin", e);
}
admin.setMemberGroups(newGroups);
}//endif
LookupLocator loc = QAConfig.getConstrainedLocator(regProxy.getLocator());
return new LocatorGroupsPair(loc,newGroups);
}//end replaceMemberGroups
/** Depending on the value of the boolean parameter <code>alternate</code>,
* this method either replaces the current member groups of the
* given lookup service (<code>generator</code>) with a new set
* of groups containing NONE of the current groups of interest
* (<code>alternate</code> == <code>false</code>), or a new set
* of groups in which, alternately, half the elements are equal
* to their counterparts in the original set, and half are different
* from their counterparts.
*
* This method is intended to guarantee that the new set of groups
* that replaces the member groups of the given lookup service contains
* some, if not all, new groups different from the original groups.
*
* This method returns an instance of <code>LocatorGroupsPair</code>
* in which the locator of the given lookup service is paired with the
* set of new groups generated by this method.
*/
protected LocatorGroupsPair replaceMemberGroups(Object generator,
boolean alternate)
throws RemoteException
{
ServiceRegistrar regProxy = null;
DiscoveryAdmin admin = null;
// only prepare the real proxy (until simulators are secure)
if(generator instanceof DiscoveryProtocolSimulator) {
regProxy
= ((DiscoveryProtocolSimulator)generator).getLookupProxy();
admin = (DiscoveryAdmin)( ((Administrable)regProxy).getAdmin() );
} else {
regProxy = (ServiceRegistrar)generator;
admin = (DiscoveryAdmin)( ((Administrable)regProxy).getAdmin() );
try {
admin = (DiscoveryAdmin)
getConfig().prepare("test.reggieAdminPreparer", admin);
} catch (TestException e) {
throw new RemoteException("Problem preparing admin", e);
}
}//endif
String[] groups = admin.getMemberGroups();
String[] newGroups = ( (groups.length > 0) ?
(new String[groups.length]) :
(new String[] {"Group_"+regProxy.getServiceID()}) );
if(newGroups.length == 0) {
logger.log(Level.FINE, " NO_GROUPS");
} else {
for(int i=0;i<newGroups.length;i++) {
boolean oddIndx = !((i%2) == 0);
newGroups[i] = ( (alternate && oddIndx) ? new String(groups[i])
: new String(groups[i]+"_new") );
logger.log(Level.FINE, " newGroups["+i+"] = "
+newGroups[i]);
}//end loop
}//endif
return replaceMemberGroups(generator,newGroups);
}//end replaceMemberGroups
/** Depending on the value of the boolean parameter <code>alternate</code>,
* for each lookup service that has been started, this method either
* replaces the current member groups of the lookup service with a
* new set of groups containing NONE of the current groups of interest
* (<code>alternate</code> == <code>false</code>), or a new set of
* groups in which, alternately, half the elements are equal to their
* counterparts in the original set, and half are different from their
* counterparts.
*
* This method is intended to guarantee that the new set of groups
* that replaces the member groups of each lookup service that was
* started contains some, if not all, new groups different from the
* original groups.
*
* This method returns an <code>ArrayList</code> in which each element
* is an instance of <code>LocatorGroupsPair</code> corresponding to one
* of the lookup services that was started; and in which the locator of
* the associated lookup service is paired with the set of new groups
* generated by this method.
*
* This method can be used to cause various discovered/discarded/changed
* events to be sent by the discovery helper utility.
*/
protected ArrayList replaceMemberGroups(boolean alternate) {
ArrayList locGroupsList = new ArrayList(genMap.size());
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
/* Replace the member groups of the current lookup service */
logger.log(Level.FINE, " lookup service "+i+" - "
+"replacing member groups with -- ");
try {
locGroupsList.add(replaceMemberGroups(iter.next(),alternate));
} catch(RemoteException e) {
logger.log(Level.FINE,
" failed to change member groups "
+"for lookup service "+i);
e.printStackTrace();
}
}//end loop
return locGroupsList;
}//end replaceMemberGroups
/** For each lookup service that has been started, this method replaces
* the lookup service's current member groups with a new set of groups
* containing NONE of the current groups of interest.
*
* This method is intended to guarantee that the member groups of each of
* the lookup services that has been started will be changed to a set
* of groups which contains NONE of the original member groups of the
* associated lookup service, and also contains NONE of the groups the
* discovery helper utility is currently interested in discovering.
*
* This method returns an <code>ArrayList</code> in which each element
* is an instance of <code>LocatorGroupsPair</code> corresponding to one
* of the lookup services that was started; and in which the locator of
* the associated lookup service is paired with the set of new groups
* generated by this method.
*
* This method can be used to cause various discovered/discarded/changed
* events to be sent by the discovery helper utility.
*/
protected ArrayList replaceMemberGroups() {
return replaceMemberGroups(false);
}//end replaceMemberGroups
/** For each lookup service that has been started, this method replaces
* the lookup service's current member groups with the given set of
* groups.
*
* This method returns an <code>ArrayList</code> in which each element
* is an instance of <code>LocatorGroupsPair</code> corresponding to one
* of the lookup services that was started; and in which the locator of
* the associated lookup service is paired with given set of groups.
*/
protected ArrayList replaceMemberGroups(String[] newGroups) {
return replaceMemberGroups(genMap.size(),newGroups);
}//end replaceMemberGroups
/** For N of the lookup services started, this method replaces the lookup
* service's current member groups with the given set of groups; where
* N is determined by the value of the given <code>nReplacements</code>
* parameter.
*
* This method returns an <code>ArrayList</code> in which each element
* is an instance of <code>LocatorGroupsPair</code> corresponding to one
* of the lookup services that was started; and in which the locator of
* the associated lookup service is paired with the given set of groups.
*/
protected ArrayList replaceMemberGroups(int nReplacements,
String[] newGroups)
{
ArrayList locGroupsList = new ArrayList(genMap.size());
Iterator iter = genMap.keySet().iterator();
for(int i=0;iter.hasNext();i++) {
Object generator = iter.next();
if(i<nReplacements) {
/* Replace the member groups of the current lookup service */
logger.log(Level.FINE, " lookup service "+i+" - "
+"replacing member groups with --");
if(newGroups.length == 0) {
logger.log(Level.FINE, " NO_GROUPS");
} else {
for(int j=0;j<newGroups.length;j++) {
logger.log(Level.FINE, " newGroups["+j+"] = "
+newGroups[j]);
}//end loop
}//endif
try {
locGroupsList.add
( replaceMemberGroups(generator,newGroups) );
} catch(RemoteException e) {
logger.log(Level.FINE,
" failed to change member groups "
+"for lookup service "+i);
e.printStackTrace();
}
} else {//(i >= nReplacements)
/* Leave member groups of the current lookup service as is*/
logger.log(Level.FINE, " lookup service "+i+" - "
+"leaving member groups unchanged --");
ServiceRegistrar regProxy = null;
if(generator instanceof DiscoveryProtocolSimulator) {
regProxy
= ((DiscoveryProtocolSimulator)generator).getLookupProxy();
} else {
regProxy = (ServiceRegistrar)generator;
}//endif
try {
LookupLocator loc = QAConfig.getConstrainedLocator(regProxy.getLocator());
String[] groups = regProxy.getGroups();
if(groups.length == 0) {
logger.log(Level.FINE, " NO_GROUPS");
} else {
for(int j=0;j<groups.length;j++) {
logger.log(Level.FINE, " groups["+j+"] = "
+groups[j]);
}//end loop
}//endif
locGroupsList.add
( new LocatorGroupsPair(loc,groups) );
} catch(RemoteException e) {
logger.log(Level.FINE,
" failed on locator/groups retrieval "
+"for lookup service "+i);
e.printStackTrace();
}
}//endif
}//end loop
return locGroupsList;
}//end replaceMemberGroups
/** Convenience method that can be used to start, at a single point
* during the current test run, all of the lookup discovery services
* needed by that test run. Useful when all of the lookup discovery
* services are to be started during setup processing.
*/
protected void startAllLDS() throws Exception {
startInitLDS();
startAddLDS();
}//end startAllLDS
/** Convenience method that can be used to start, at a single point
* during the current test run, all of the lookup discovery services
* INITIALLY needed by that test run. Useful when an initial set of
* lookup discovery services are to be started during setup processing,
* and (possibly) an additional set of lookup discovery services are to
* be started at some later time, after the test has already begun
* execution.
*/
protected void startInitLDS() throws Exception {
if(nLookupDiscoveryServices > 0) {
/* Skip over remote LDSs to the indices of the local LDSs */
int n0 = nRemoteLookupDiscoveryServices
+ nAddRemoteLookupDiscoveryServices;
int n1 = n0 + nLookupDiscoveryServices;
for(int i=n0;i<n1;i++) {
startLDS(i,(ToJoinPair)initLDSToStart.get(i));
}//end loop
}//endif(nLookupDiscoveryServices > 0)
}//end startInitLDS
/** Convenience method that can be used to start, at a single point
* during the current test run, any additional lookup discovery services
* needed by that test run. Useful when an initial set of lookup discovery
* services are to be started during setup processing, and an additional
* set of lookup discovery services are to be started at some later time,
* after the test has already begun execution.
*/
protected void startAddLDS() throws Exception {
if(nAddLookupDiscoveryServices > 0) {
/* Skip over remote LDSs and LDSs already started to the
* indices of the additional local LDSs
*/
int n0 = nRemoteLookupDiscoveryServices
+ nAddRemoteLookupDiscoveryServices
+ ldsList.size();
int n1 = n0 + nAddLookupDiscoveryServices;
for(int i=n0;i<n1;i++) {
int j = i-n0;
startLDS(i,(ToJoinPair)addLDSToStart.get(j));
}//end loop
}//endif(nAddLookupDiscoveryServices > 0)
}//end startAddLDS
/** Convenience method that can be used to start, at any point during
* the current test run, a single lookup discovery service with
* configuration referenced by the given parameter values. Useful when
* individual lookup discovery services are to be started at different
* points in time during the test run, or when a set of lookup discovery
* services are to be started from within a loop.
*/
protected void startLDS(int indx, ToJoinPair tojoinPair) throws Exception {
logger.log(Level.FINE, " starting lookup discovery service "
+indx);
/* the returned proxy is already prepared using the preparer named
* by the service preparername property
*/
LookupDiscoveryService ldsProxy =
(LookupDiscoveryService)(manager.startService
("net.jini.discovery.LookupDiscoveryService"));
/* Force non-unique groups for manual tests */
if( (testType == MANUAL_TEST_REMOTE_COMPONENT)
|| (testType == MANUAL_TEST_LOCAL_COMPONENT) )
{
if(ldsProxy instanceof Administrable) {
Object admin = ((Administrable)ldsProxy).getAdmin();
admin = getConfig().prepare("test.fiddlerAdminPreparer", admin);
if(admin instanceof JoinAdmin) {
((JoinAdmin)admin).setLookupGroups(tojoinPair.groups);
}//endif
}//endif
}//endif
ldsList.add( ldsProxy );
expectedServiceList.add( ldsProxy );
LocatorsUtil.displayLocatorSet(tojoinPair.locators,
" locators to join",Level.FINE);
GroupsUtil.displayGroupSet(tojoinPair.groups,
" groups to join",Level.FINE);
}//end startLDS
/* Retrieves/stores/displays configuration values for the current test */
private void getSetupInfo() {
testType = getConfig().getIntConfigVal("com.sun.jini.testType",
AUTOMATIC_LOCAL_TEST);
/* begin harness info */
logger.log(Level.FINE, " ----- Harness Info ----- ");
String harnessCodebase = System.getProperty("java.rmi.server.codebase",
"no codebase");
logger.log(Level.FINE,
" harness codebase -- "
+harnessCodebase);
String harnessClasspath = System.getProperty("java.class.path",
"no classpath");
logger.log(Level.FINE,
" harness classpath -- "
+harnessClasspath);
String discDebug = System.getProperty("net.jini.discovery.debug",
"false");
logger.log(Level.FINE,
" net.jini.discovery.debug -- "
+discDebug);
String regDebug = System.getProperty("com.sun.jini.reggie.proxy.debug",
"false");
logger.log(Level.FINE,
" com.sun.jini.reggie.proxy.debug -- "
+regDebug);
String joinDebug = System.getProperty("com.sun.jini.join.debug",
"false");
logger.log(Level.FINE,
" com.sun.jini.join.debug -- "
+joinDebug);
String sdmDebug = System.getProperty("com.sun.jini.sdm.debug","false");
logger.log(Level.FINE,
" com.sun.jini.sdm.debug -- "
+sdmDebug);
maxSecsEventWait = getConfig().getIntConfigVal
("net.jini.discovery.maxSecsEventWait",
maxSecsEventWait);
logger.log(Level.FINE,
" max secs event wait -- "
+maxSecsEventWait);
/* end harness info */
/* begin lookup info */
logger.log(Level.FINE, " ----- Lookup Service Info ----- ");
implClassname = getConfig().getStringConfigVal
("net.jini.core.lookup.ServiceRegistrar.impl",
"no implClassname");
nLookupServices = getConfig().getIntConfigVal
("net.jini.lookup.nLookupServices",
nLookupServices);
nRemoteLookupServices = getConfig().getIntConfigVal
("net.jini.lookup.nRemoteLookupServices",
nRemoteLookupServices);
nAddLookupServices = getConfig().getIntConfigVal
("net.jini.lookup.nAddLookupServices",
nAddLookupServices);
nAddRemoteLookupServices = getConfig().getIntConfigVal
("net.jini.lookup.nAddRemoteLookupServices",
nAddRemoteLookupServices);
if(testType == MANUAL_TEST_REMOTE_COMPONENT) {
nLookupServices = nRemoteLookupServices;
nAddLookupServices = nAddRemoteLookupServices;
nRemoteLookupServices = 0;
nAddRemoteLookupServices = 0;
}//endif
logger.log(Level.FINE,
" # of lookup services to start -- "
+nLookupServices);
logger.log(Level.FINE,
" # of additional lookup services to start -- "
+nAddLookupServices);
nSecsLookupDiscovery = getConfig().getIntConfigVal
("net.jini.lookup.nSecsLookupDiscovery",
nSecsLookupDiscovery);
logger.log(Level.FINE,
" seconds to wait for discovery -- "
+nSecsLookupDiscovery);
/* Multicast announcement info - give priority to the command line */
try {
int sysInterval = Integer.getInteger
("net.jini.discovery.announce",0).intValue();
originalAnnounceInterval = sysInterval;
if(sysInterval > 0) {
announceInterval = sysInterval;
} else {
sysInterval = getConfig().getIntConfigVal
("net.jini.discovery.announce",0);
if(sysInterval > 0) announceInterval = sysInterval;
}
Properties props = System.getProperties();
props.put("net.jini.discovery.announce",
(new Integer(announceInterval)).toString());
System.setProperties(props);
} catch (SecurityException e) { }
logger.log(Level.FINE,
" discard if no announcements in (nSecs =) -- "
+(announceInterval/1000));
minNAnnouncements = getConfig().getIntConfigVal
("net.jini.discovery.minNAnnouncements",
minNAnnouncements);
nIntervalsToWait = getConfig().getIntConfigVal
("net.jini.discovery.nIntervalsToWait",
nIntervalsToWait);
/* end lookup info */
fastTimeout =
getConfig().getIntConfigVal("com.sun.jini.test.share.fastTimeout",
fastTimeout);
/* begin local/serializable service info */
nServices = getConfig().getIntConfigVal("net.jini.lookup.nServices",nServices);
nAddServices = getConfig().getIntConfigVal("net.jini.lookup.nAddServices",
nAddServices);
if( (nServices+nAddServices) > 0) {
logger.log(Level.FINE,
" ----- General Service Info ----- ");
logger.log(Level.FINE,
" # of initial basic services to register -- "
+nServices);
logger.log(Level.FINE,
" # of additional basic srvcs to register -- "
+nAddServices);
nAttributes = getConfig().getIntConfigVal("net.jini.lookup.nAttributes",
nAttributes);
logger.log(Level.FINE,
" # of attributes per service -- "
+nAttributes);
nAddAttributes = getConfig().getIntConfigVal
("net.jini.lookup.nAddAttributes",
nAddAttributes);
logger.log(Level.FINE,
" # of additional attributes per service -- "
+nAddAttributes);
nSecsJoin = getConfig().getIntConfigVal
("net.jini.lookup.nSecsJoin",
nSecsJoin);
logger.log(Level.FINE,
" # of seconds to wait for service join -- "
+nSecsJoin);
nSecsServiceDiscovery = getConfig().getIntConfigVal
("net.jini.lookup.nSecsServiceDiscovery",
nSecsServiceDiscovery);
logger.log(Level.FINE,
" # of secs to wait for service discovery -- "
+nSecsServiceDiscovery);
}//endif(nServices+nAddServices > 0)
/* begin lookup discovery service info */
nLookupDiscoveryServices = getConfig().getIntConfigVal
("net.jini.discovery.nLookupDiscoveryServices",
nLookupDiscoveryServices);
nRemoteLookupDiscoveryServices = getConfig().getIntConfigVal
("net.jini.discovery.nRemoteLookupDiscoveryServices",
nRemoteLookupDiscoveryServices);
nAddLookupDiscoveryServices = getConfig().getIntConfigVal
("net.jini.discovery.nAddLookupDiscoveryServices",
nAddLookupDiscoveryServices);
nAddRemoteLookupDiscoveryServices = getConfig().getIntConfigVal
("net.jini.discovery.nAddRemoteLookupDiscoveryServices",
nAddRemoteLookupDiscoveryServices);
if(testType == MANUAL_TEST_REMOTE_COMPONENT) {
nLookupDiscoveryServices = nRemoteLookupDiscoveryServices;
nAddLookupDiscoveryServices = nAddRemoteLookupDiscoveryServices;
nRemoteLookupDiscoveryServices = 0;
nAddRemoteLookupDiscoveryServices = 0;
}//endif
int tmpN = nLookupDiscoveryServices
+ nAddLookupDiscoveryServices
+ nRemoteLookupDiscoveryServices
+ nAddRemoteLookupDiscoveryServices;
if(tmpN > 0) {
logger.log(Level.FINE,
" ----- Lookup Discovery Service Info ----- ");
logger.log(Level.FINE,
" # of lookup discovery services to start -- "
+nLookupDiscoveryServices);
logger.log(Level.FINE,
" # of additional lookup discovery srvcs -- "
+nAddLookupDiscoveryServices);
}//endif(tmpN > 0)
/* begin lease renewal service info */
nLeaseRenewalServices = getConfig().getIntConfigVal
("net.jini.lease.nLeaseRenewalServices",
nLeaseRenewalServices);
nRemoteLeaseRenewalServices = getConfig().getIntConfigVal
("net.jini.lease.nRemoteLeaseRenewalServices",
nRemoteLeaseRenewalServices);
nAddLeaseRenewalServices = getConfig().getIntConfigVal
("net.jini.lease.nAddLeaseRenewalServices",
nAddLeaseRenewalServices);
nAddRemoteLeaseRenewalServices = getConfig().getIntConfigVal
("net.jini.lease.nAddRemoteLeaseRenewalServices",
nAddRemoteLeaseRenewalServices);
if(testType == MANUAL_TEST_REMOTE_COMPONENT) {
nLeaseRenewalServices = nRemoteLeaseRenewalServices;
nAddLeaseRenewalServices = nAddRemoteLeaseRenewalServices;
nRemoteLeaseRenewalServices = 0;
nAddRemoteLeaseRenewalServices = 0;
}//endif
tmpN = nLeaseRenewalServices+ nAddLeaseRenewalServices
+ nRemoteLeaseRenewalServices + nAddRemoteLeaseRenewalServices;
if(tmpN > 0) {
logger.log(Level.FINE,
" ----- Lease Renewal Service Info ----- ");
logger.log(Level.FINE,
" # of lease renewal services to start -- "
+nLeaseRenewalServices);
logger.log(Level.FINE,
" # of additional lease renewal srvcs -- "
+nAddLeaseRenewalServices);
}//endif(tmpN > 0)
/* begin event mailbox service info */
nEventMailboxServices = getConfig().getIntConfigVal
("net.jini.event.nEventMailboxServices",
nEventMailboxServices);
nRemoteEventMailboxServices = getConfig().getIntConfigVal
("net.jini.event.nRemoteEventMailboxServices",
nRemoteEventMailboxServices);
nAddEventMailboxServices = getConfig().getIntConfigVal
("net.jini.event.nAddEventMailboxServices",
nAddEventMailboxServices);
nAddRemoteEventMailboxServices = getConfig().getIntConfigVal
("net.jini.event.nAddRemoteEventMailboxServices",
nAddRemoteEventMailboxServices);
if(testType == MANUAL_TEST_REMOTE_COMPONENT) {
nEventMailboxServices = nRemoteEventMailboxServices;
nAddEventMailboxServices = nAddRemoteEventMailboxServices;
nRemoteEventMailboxServices = 0;
nAddRemoteEventMailboxServices = 0;
}//endif
tmpN = nEventMailboxServices+ nAddEventMailboxServices
+ nRemoteEventMailboxServices + nAddRemoteEventMailboxServices;
if(tmpN > 0) {
logger.log(Level.FINE,
" ----- Event Mailbox Service Info ----- ");
logger.log(Level.FINE,
" # of event mailbox services to start -- "
+nEventMailboxServices);
logger.log(Level.FINE,
" # of additional event mailbox srvcs -- "
+nAddEventMailboxServices);
}//endif(tmpN > 0)
/* Handle remote/local components of manual tests */
remoteHost = getConfig().getStringConfigVal("net.jini.lookup.remotehost",
remoteHost);
switch(testType) {
case MANUAL_TEST_REMOTE_COMPONENT:
logger.log(Level.FINE,
" ***** REMOTE COMPONENT OF A MANUAL TEST "
+"(remote host = "+remoteHost+") ***** ");
break;
case MANUAL_TEST_LOCAL_COMPONENT:
logger.log(Level.FINE,
" ***** LOCAL COMPONENT OF A MANUAL TEST "
+"(remote host = "+remoteHost+") ***** ");
logger.log(Level.FINE,
" ----- Remote Lookup Service Info ----- ");
logger.log(Level.FINE,
" # of remote lookup services -- "
+nRemoteLookupServices);
logger.log(Level.FINE,
" # of additional remote lookup services -- "
+nAddRemoteLookupServices);
logger.log(Level.FINE,
" # of remote basic services -- "
+nServices);
logger.log(Level.FINE,
" ----- Remote Lookup Discovery Service Info ----- ");
logger.log(Level.FINE,
" # of remote lookup discovery services -- "
+nRemoteLookupDiscoveryServices);
logger.log(Level.FINE,
" additional remote lookup discovery srvcs -- "
+nAddRemoteLookupDiscoveryServices);
logger.log(Level.FINE,
" ----- Remote Lease Renewal Service Info ----- ");
logger.log(Level.FINE,
" # of remote lease renewal services -- "
+nRemoteLeaseRenewalServices);
logger.log(Level.FINE,
" additional remote lease renewal srvcs -- "
+nAddRemoteLeaseRenewalServices);
logger.log(Level.FINE,
" ----- Remote Event Mailbox Service Info ----- ");
logger.log(Level.FINE,
" # of remote event mailbox services -- "
+nRemoteEventMailboxServices);
logger.log(Level.FINE,
" additional remote event mailbox srvcs -- "
+nAddRemoteEventMailboxServices);
break;
}//end switch(testType)
}//end getSetupInfo
/** Retrieves and stores the information needed to configure any lookup
* services that will be started for the current test run.
*/
private void getLookupInfo() throws TestException {
/* Retrieve the member groups & locator of each lookup */
/* For all cases except MANUAL_TEST_LOCAL_COMPONENT, the number of
* remote lookups is zero (see getSetupInfo). For that case, we must
* handle the remote lookup services BEFORE handling the local lookups.
* This is because the local component may be both starting local
* lookups, and discovering remote lookups; but the remote component
* will only be starting the remote lookups, and will therefore have
* no knowledge of the local lookups. Because the groups and ports are
* ordered by the index numbers in the config file, if the local info
* were to be handled first, then the local component of the test
* would fall out of alignment with the remote component.
*/
int n0 = 0;
int n1 = n0 + nRemoteLookupServices;
for(int i=0;i<n1;i++) {//initial remote lookups
/* Member groups for remote lookup service i */
String groupsArg = getConfig().getServiceStringProperty
("net.jini.core.lookup.ServiceRegistrar",
"membergroups", i);
/* Do NOT use unique groups names since clocks on the local
* and remote sides are not synchronized, and host names are
* different
*/
String[] memberGroups = config.parseString(groupsArg,",");
if(memberGroups == DiscoveryGroupManagement.ALL_GROUPS) {
logger.log(Level.FINER, "memberGroups = ALL_GROUPS");
continue;
}
memberGroupsList.add(memberGroups);
/* Locator for initial remote lookup service i */
LookupLocator lookupLocator = getRemoteTestLocator(i);
initLookupsToStart.add
(new LocatorGroupsPair(lookupLocator,memberGroups));
}//end loop
/* Remote lookups started after initial remote lookups */
n0 = n1;
n1 = n0 + nAddRemoteLookupServices;
for(int i=n0;i<n1;i++) {//additional remote lookups
/* Member groups for remote lookup service i */
String groupsArg = getConfig().getServiceStringProperty
("net.jini.core.lookup.ServiceRegistrar",
"membergroups", i);
/* Use NON-unique groups for remote lookups */
String[] memberGroups = config.parseString(groupsArg,",");
if(memberGroups == DiscoveryGroupManagement.ALL_GROUPS) continue;
memberGroupsList.add(memberGroups);
/* Locator for additional remote lookup service i */
LookupLocator lookupLocator = getRemoteTestLocator(i);
addLookupsToStart.add
(new LocatorGroupsPair(lookupLocator,memberGroups));
}//end loop
/* Handle all lookups to be started locally */
n0 = n1;
n1 = n0 + nLookupServices;
int portBias = n0;
for(int i=n0;i<n1;i++) {//initial local lookups
/* Member groups for lookup service i */
String groupsArg = getConfig().getServiceStringProperty
("net.jini.core.lookup.ServiceRegistrar",
"membergroups", i);
if(testType == AUTOMATIC_LOCAL_TEST) {
/* Use unique group names to avoid conflict with other tests */
groupsArg = config.makeGroupsUnique(groupsArg);
}//endif
String[] memberGroups = config.parseString(groupsArg,",");
if(memberGroups == DiscoveryGroupManagement.ALL_GROUPS) {
logger.log(Level.FINER, "memberGroups = All_Groups");
continue;
}
memberGroupsList.add(memberGroups);
/* Locator for initial lookup service i */
LookupLocator lookupLocator = getTestLocator(i-portBias);
initLookupsToStart.add
(new LocatorGroupsPair(lookupLocator,memberGroups));
}//end loop
/* The lookup services to start after the initial lookup services */
n0 = n1;
n1 = n0 + nAddLookupServices;
for(int i=n0;i<n1;i++) {//additional local lookups
/* Member groups for lookup service i */
String groupsArg = getConfig().getServiceStringProperty
("net.jini.core.lookup.ServiceRegistrar",
"membergroups", i);
if(testType == AUTOMATIC_LOCAL_TEST) {
/* Use unique group names to avoid conflict with other tests */
groupsArg = config.makeGroupsUnique(groupsArg);
}//endif
String[] memberGroups = config.parseString(groupsArg,",");
if(memberGroups == DiscoveryGroupManagement.ALL_GROUPS) continue;
memberGroupsList.add(memberGroups);
/* Locator for additional lookup service i */
LookupLocator lookupLocator = getTestLocator(i-portBias);
addLookupsToStart.add
(new LocatorGroupsPair(lookupLocator,memberGroups));
}//end loop
/* Populate the ArrayList allLookupsToStart */
for(int i=0;i<initLookupsToStart.size();i++) {
allLookupsToStart.add(initLookupsToStart.get(i));
}//end loop
for(int i=0;i<addLookupsToStart.size();i++) {
allLookupsToStart.add(addLookupsToStart.get(i));
}//end loop
}//end getLookupInfo
/** Method used for debugging. Displays the following information about
* the contents of the given list of <code>LocatorGroupsPair</code>
* instances: the number of elements, the locator of the associated
* lookup service, and the member groups of the associated lookup service.
*/
private void displayLookupStartInfo(List lookupList) {
logger.log(Level.FINE, " # of lookups = "
+lookupList.size());
for(int i=0;i<lookupList.size();i++) {
LocatorGroupsPair pair = (LocatorGroupsPair)lookupList.get(i);
LookupLocator loc = pair.locator;
String[] groups = pair.groups;
logger.log(Level.FINE,
" locator lookup["+i+"] = "+loc);
GroupsUtil.displayGroupSet(groups," group",
Level.FINE);
}//end loop
}//end displayLookupStartInfo
/** Retrieves and stores the information needed to configure any lookup
* discovery services that will be started for the current test run.
*/
private void getLDSInfo() {
/* Retrieve groups/locators each lookup discovery service should join*/
int n0 = 0;
int n1 = n0 + nRemoteLookupDiscoveryServices;
for(int i=0;i<n1;i++) {//initial remote lookup discovery services
/* Locators and groups to join */
String tojoinArg = getConfig().getServiceStringProperty
("net.jini.discovery.LookupDiscoveryService",
"tojoin", i);
/* Do NOT use unique groups names since clocks on the local
* and remote sides are not synchronized, and host names are
* different
*/
LookupLocator[] locsToJoin = getLocatorsFromToJoinArg(tojoinArg);
String[] groupsToJoin = getGroupsFromToJoinArg(tojoinArg);
initLDSToStart.add(new ToJoinPair(locsToJoin,groupsToJoin));
}//end loop
/*Remote lookup discovery servicess started after initial remote LDSs*/
n0 = n1;
n1 = n0 + nAddRemoteLookupDiscoveryServices;
for(int i=n0;i<n1;i++) {//additional remote lookup discovery services
/* Locators and groups to join */
String tojoinArg = getConfig().getServiceStringProperty
("net.jini.discovery.LookupDiscoveryService",
"tojoin", i);
/* Use NON-unique groups to join */
LookupLocator[] locsToJoin = getLocatorsFromToJoinArg(tojoinArg);
String[] groupsToJoin = getGroupsFromToJoinArg(tojoinArg);
addLDSToStart.add(new ToJoinPair(locsToJoin,groupsToJoin));
}//end loop
/* Handle all lookup discovery services to be started locally */
n0 = n1;
n1 = n0 + nLookupDiscoveryServices;
for(int i=n0;i<n1;i++) {//initial local lookup discovery services
/* Locators and groups to join */
String tojoinArg = getConfig().getServiceStringProperty
("net.jini.discovery.LookupDiscoveryService",
"tojoin", i);
if(testType == AUTOMATIC_LOCAL_TEST) {//use unique group names
tojoinArg = config.makeGroupsUnique(tojoinArg);
}//endif
LookupLocator[] locsToJoin = getLocatorsFromToJoinArg(tojoinArg);
String[] groupsToJoin = getGroupsFromToJoinArg(tojoinArg);
initLDSToStart.add(new ToJoinPair(locsToJoin,groupsToJoin));
}//end loop
/* The LDSs to start after the initial LDSs */
n0 = n1;
n1 = n0 + nAddRemoteLookupDiscoveryServices;
for(int i=n0;i<n1;i++) {//additional local lookup discovery services
/* Locators and groups to join */
String tojoinArg = getConfig().getServiceStringProperty
("net.jini.discovery.LookupDiscoveryService",
"tojoin", i);
if(testType == AUTOMATIC_LOCAL_TEST) {//use unique group names
tojoinArg = config.makeGroupsUnique(tojoinArg);
}//endif
LookupLocator[] locsToJoin = getLocatorsFromToJoinArg(tojoinArg);
String[] groupsToJoin = getGroupsFromToJoinArg(tojoinArg);
addLDSToStart.add(new ToJoinPair(locsToJoin,groupsToJoin));
}//end loop
/* Populate the ArrayList allLDSToStart */
for(int i=0;i<initLDSToStart.size();i++) {
allLDSToStart.add(initLDSToStart.get(i));
}//end loop
for(int i=0;i<addLDSToStart.size();i++) {
allLDSToStart.add(addLDSToStart.get(i));
}//end loop
}//end getLDSInfo
/** Convenience method that creates an array of Class objects in which
* element corresponds to a different service class type that will be
* started remotely and/or locally. The array returned by this method
* can be used when building templates that will be used to match on
* class type.
*/
protected Class[] getServiceClassArray() {
ArrayList classnamesList = new ArrayList(5);
ArrayList loadedClassList = new ArrayList(expectedServiceList.size());
if( (nLookupDiscoveryServices+nRemoteLookupDiscoveryServices) > 0) {
classnamesList.add
(new String("net.jini.discovery.LookupDiscoveryService") );
}//endif
if( (nLeaseRenewalServices+nRemoteLeaseRenewalServices) > 0) {
classnamesList.add
(new String("net.jini.lease.LeaseRenewalService") );
}//endif
if( (nEventMailboxServices+nRemoteEventMailboxServices) > 0) {
classnamesList.add(new String("net.jini.event.EventMailbox") );
}//endif
for(int i=0;i<classnamesList.size();i++) {
String classname = (String)classnamesList.get(i);
try {
loadedClassList.add(Class.forName(classname));
} catch(ClassNotFoundException e) {
logger.log(Level.FINE,
" ClassNotFoundException while loading "
+"service class "+classname);
e.printStackTrace();
}//end try
}//end loop
return ( (Class[])loadedClassList.toArray
(new Class[loadedClassList.size()]) );
}//end getServiceClassArray
/** Special-purpose method that should be called by the remote component
* of a manual test after that component of the test has started all of
* the services for which it was configured. This method is useful
* in such a manual test scenario because it is generally desirable for
* the remote component to enter into a "wait state" so that the local
* component of the test can run and interact with the remote component
* without having to worry about the remote component shutting down
* unexpectedly.
*/
protected void waitForKeyboardInput() {
System.out.println(" start test in separate VM ... ");
System.out.println(" ***** WHEN DONE, PRESS ANY KEY TO EXIT *****");
try {
int c=System.in.read();
} catch (IOException e) { }
}//end waitForKeyboardInput
/** Convenience method that examines the given <code>String</code>
* containing a comma-separated list of groups and locators to join,
* and returns a <code>String</code> array containing the items that
* correspond to the groups to join.
*/
private String[] getGroupsFromToJoinArg(String tojoinArg) {
String[] tojoin = config.parseString(tojoinArg,",");
if(tojoin == null) return DiscoveryGroupManagement.ALL_GROUPS;
if(tojoin.length == 0) return DiscoveryGroupManagement.NO_GROUPS;
ArrayList tojoinList = new ArrayList(tojoin.length);
for(int i=0;i<tojoin.length;i++) {
if( !config.isLocator(tojoin[i]) ) tojoinList.add(tojoin[i]);
}//end loop
return ( (String[])tojoinList.toArray(new String[tojoinList.size()]) );
}//end getGroupsFromToJoinArg
/** Convenience method that examines the given <code>String</code>
* containing a comma-separated list of groups and locators to join,
* and returns a <code>LookupLocator</code> array containing the items
* that correspond to the locators to join.
*/
//this method obtain constrainable locators because the locators are
// administratively set after the service is started. It's not clear whether
// this can be discarded in favor of the new initialLookupLocators configuration
// entry
private LookupLocator[] getLocatorsFromToJoinArg(String tojoinArg) {
String[] tojoin = config.parseString(tojoinArg,",");
if(tojoin == null) return new LookupLocator[0];
if(tojoin.length == 0) return new LookupLocator[0];
ArrayList tojoinList = new ArrayList(tojoin.length);
for(int i=0;i<tojoin.length;i++) {
try {
tojoinList.add(QAConfig.getConstrainedLocator(tojoin[i]));
} catch(MalformedURLException e) {
continue;//not a valid locator (must be group), try next one
}
}//end loop
return ( (LookupLocator[])tojoinList.toArray
(new LookupLocator[tojoinList.size()]) );
}//end getLocatorsFromToJoinArg
}//end class BaseQATest