You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2012/01/21 08:28:36 UTC
svn commit: r1234278 [23/29] - in /river/tck: ./ configs/ doc/ doc/api/
doc/api/com/ doc/api/com/sun/ doc/api/com/sun/jini/
doc/api/com/sun/jini/compat/ doc/api/com/sun/jini/compat/admin1/
doc/api/com/sun/jini/compat/admin2/ doc/api/com/sun/jini/compat...
Added: river/tck/src/com/sun/jini/compat/start/StartUtil.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/start/StartUtil.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/start/StartUtil.java (added)
+++ river/tck/src/com/sun/jini/compat/start/StartUtil.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,1260 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.start;
+
+import com.sun.jini.debug.Debug;
+import com.sun.jini.compat.start.ParsedArgs;
+
+import net.jini.discovery.DiscoveryGroupManagement;
+
+import net.jini.core.discovery.LookupLocator;
+
+import java.io.File;
+import java.io.PrintWriter;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import java.security.AccessController;
+
+import java.text.MessageFormat;
+
+import java.util.ArrayList;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+/**
+ * This class provides utilities that can be useful when starting clients
+ * or services. In particular, this class can be useful when starting a
+ * version of a service that is activatable and persistent (referred to
+ * as an <i>activatable</i> version), an activatable version that is able to
+ * share an activation group with other activatable services (referred to
+ * as a <i>shared-activatable</i> version), or a version of the service that
+ * is non-activatable and non-persistent (referred to as a <i>transient</i>
+ * version). The particular version of the service that is started as a result
+ * of employing this facility depends on the values and format of the arguments
+ * entered on the command line and contained in the <code>args</code>
+ * parameter. A particular syntax and format for the command line arguments
+ * is required when starting a service using this facility.
+ * <p>
+ * To start an activatable service:
+ * <p>
+ * If the service being started is an activatable service, then not only
+ * are the first three arguments required, but they must be input in a
+ * pre-defined order. The remaining arguments are optional and can occur
+ * in any order. Although the number of arguments that follow the first
+ * three required arguments has no limit, they fall into one of four
+ * categories: the "groups" argument, the "locators" argument, the
+ * "java program" argument, and the "properties & options" argument. The
+ * optional arguments can be input to the command line in one of two
+ * formats. The first format imposes no order on the optional arguments.
+ * The second format is allowed so that scripts written to start services
+ * that follow the command line syntax from previous releases, remain
+ * compatible. This second format of the command line imposes a particular
+ * order and format on the optional arguments; whereas the new format is
+ * less restrictive.
+ * <P>
+ * The required format of the command line is as follows:
+ * <p>
+ * <pre>
+ * The new, less restrictive format -
+ * <p>
+ * codebase policyfile logdir [ [group0] [group1] [group2] ... ]
+ * [ [locator0] [locator1] [locator2] ... ]
+ * [javaprogram]
+ * [ [property0] [option0] [property1] ... ]
+ * <p>
+ * where the first three arguments are required and must appear in the
+ * order shown above, and the remaining arguments are optional and can
+ * appear in any order
+ * </pre>
+ * <p>
+ * <pre>
+ * The original format -
+ * <p>
+ * codebase policyfile logdir
+ * [group0,locator0,locator1,group1,locator2 ... ]
+ * [javaprogram]
+ * [ [property0] [option0] [property1] ... ]
+ * <p>
+ * where the first three arguments are required and the remaining
+ * arguments are optional, but must appear in the order shown above.
+ * Note that although the fourth argument above contains both groups
+ * and locators, it is actually a single argument; with the groups
+ * and locators delimited by commas (with no spaces). Note also that
+ * in earlier releases, locators were not recognized.
+ * </pre>
+ * <p>
+ * For each of the arguments, both required and optional, the following
+ * formats are imposed:
+ * <p>
+ * <pre>
+ * codebase: '"http://<hostname>:<port>/jarFile.jar"'
+ * <p> or
+ * '"http://<hostname>:<port>/<directoryPath>/"'
+ * <p>
+ * policyfile: '<directoryPath>/<policyFilename>'
+ * <p>
+ * logdir: '<directoryPath>/<logFilename>'
+ * <p>
+ * group: 'any String not in the jini protocol format'
+ * <p>
+ * locator: 'String in the jini protocol format
+ * <p> 'jini://<hostname>:[<port>]' (the port is optional)
+ * <p>
+ * javaprogram: '<directoryPath>/<nameOfFileToExecute>'
+ * <p>
+ * property: '-Dmy.property0=propVal0 -Dmy.property1=propVal1 ...'
+ * <p>
+ * option: '-classpath <classpath value> ...'
+ * </pre>
+ * <p>
+ * An example command line might be something like the following (note
+ * that this example is broken into separate lines and annotated
+ * for readability):
+ * <p>
+ * <pre>
+ * java -jar myService.jar // the service to start using jar execution
+ * <p> "http://myHost:8081/myService-dl.jar" // codebase
+ * <p> /home/myDir/myService.policy // policy
+ * <p> /tmp/myServiceLog0 // log dir
+ * <p> com.my.service.group,jini://yourHost // group & locator
+ * <p> /export/progs/jdk1.3/java // java prog to run
+ * <p> -classpath /files/jdk1.2/lib // option0
+ * <p> -Dcom.sun.jini.discovery.debug=true // property0
+ * <p> -Dcom.sun.jini.reggie.proxy.debug=true // property1
+ * <p> -Djava.compiler= // property2
+ * <p>
+ * </pre>
+ * To start a shared-activatable service:
+ * <p>
+ * If the service being started is a shared-activatable service, then the
+ * first three and fifth arguments are required, but they must be input in a
+ * pre-defined order. The fourth argument is optional. The arguments that
+ * follow the first three required arguments fall into one of three
+ * categories: the "groups" argument, the "locators" argument,
+ * and the "sharedvm" argument.
+ * <P>
+ * <pre>
+ * The format -
+ * <p>
+ * codebase policyfile logdir
+ * [group0,locator0,locator1,group1,locator2 ... ]
+ * sharedvm_log
+ * <p>
+ * where the first three and the fifth arguments are required and the
+ * remaining arguments are optional, but must appear in the order shown
+ * above.
+ * Note that although the fourth argument above contains both groups
+ * and locators, it is actually a single argument; with the groups
+ * and locators delimited by commas (with no spaces). Note also that
+ * in earlier releases, locators were not recognized.
+ * </pre>
+ * <p>
+ * The formats for each of the arguments, both required and optional, are
+ * described above (in the "activatable service" description), except for
+ * the <code>sharedvm_log</code> argument. The <code>sharedvm_log</code>
+ * argument has the following format:
+ * <p>
+ * <pre>
+ * sharedvm_log: '<directoryPath>'
+ * </pre>
+ * where <directoryPath> refers to an existing directory path
+ * (previously) created by a shared group creation process.
+ * <p>
+ * To start a transient service:
+ * <p>
+ * If the service being started is a transient service, then the command
+ * line requires only the "log directory" argument; and accepts only the
+ * optional "groups" and "locators" arguments.
+ * <p>
+ * If the codebase, the policy file, and/or any options are desired to
+ * be set for the VM of a transient service started by this facility,
+ * those items should be set through arguments input directly to the
+ * java command used to start the service, (for the case of the transient
+ * service, this class and the service share the same VM). For example,
+ * <p>
+ * <pre>
+ * /export/progs/jdk1.3/java
+ * <p> -cp /jars/jini-core.jar:/jars/jini-ext.jar:/jars/myService.jar
+ * <p> -Dcom.sun.jini.discovery.debug=true
+ * <p> -Dcom.sun.jini.reggie.proxy.debug=true
+ * <p> -Djava.compiler=
+ * <p> -Djava.rmi.server.codebase="http:myHost:8081/myService-dl.jar"
+ * <p> -Djava.security.policy=/home/myDir/myService.policy
+ * <p> my.service.package.myService // class file to execute
+ * <p> /tmp/myServiceLog0 // log dir argument
+ * <p> group0,jini://host0,group1,jini://host1 // groups & locators
+ * <p>
+ * </pre>
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ * @see com.sun.jini.compat.start.ParsedArgs
+ */
+public class StartUtil {
+ /**
+ * Utility for outputting debug messages for this class.
+ */
+ private static final Debug debug =
+ (Debug)AccessController.doPrivileged(
+ Debug.getDebugAction("com.sun.jini.compat.start.startutil.debug"));
+
+ /**
+ * Print writer for shared group creation related debug messages.
+ */
+ private static final PrintWriter dbgParse = debug.getWriter("parse");
+
+ public static class ParsedListResult {
+ public int nArgsParsed; //total number of args that were examined
+ public Object[] extractedArgs;//groups or locs extracted from the list
+ public ParsedListResult(int nArgsParsed, Object[] extractedArgs) {
+ this.nArgsParsed = nArgsParsed;
+ this.extractedArgs = extractedArgs;
+ }
+ }//end class ParsedListResult
+
+ /** Fully-qualified package name that, together with a resource item
+ * name, identifies the resource bundle from which to retrieve
+ * resource information (which can be localized)
+ */
+ private static final String resourcePackage
+ = "com.sun.jini.compat.start.resources";
+ /** name of particular item in resource bundle that will be printed */
+ private String resourceName;
+ /** The set of resources used to enable localization */
+ private ResourceBundle resources;
+ /** The default set of groups to discover and join */
+ private String[] defaultGroups = new String[]{""}; //public group
+
+ /**
+ * Constructs a new instance of this utility class, initializing the
+ * information about the resource bundle that is used to display usage
+ * and error information.
+ *
+ * @param ResourceName the name used to identify the particular item
+ * in the resource bundle that will be printed
+ */
+ public StartUtil(String resourceName) {
+ this.resourceName = resourceName;
+ try {
+ resources = ResourceBundle.getBundle
+ (resourcePackage+"."+resourceName);
+ } catch (MissingResourceException e) {
+ e.printStackTrace();
+ }
+ }//end constructor
+
+ /**
+ * Parses the elements contained in the <code>args</code> parameter,
+ * which should contain the arguments input on the command line
+ * when requesting that a program be started. This method assumes a
+ * particular syntax and format for that command line (see this class'
+ * description for a complete description of the expected syntax).
+ * <p>
+ *
+ * @param args <code>String</code> array containing the arguments input
+ * to the command line minus any initial "required" arguments
+ * (all required parameters are assumed to have already been
+ * parsed before this method is invoked).
+ *
+ * @return instance of the class <code>ParsedArgs</code>
+ * containing the values of the arguments that were parsed.
+ * Will return <code>null</code> if the arguments cannot be
+ * parsed for any reason (for example, the argument list format
+ * is invalid).
+ *
+ * @see ParsedArgs
+ */
+ public ParsedArgs parseArgs(String[] args) {
+ return parseArgs(args,0);
+ }//end parseArgs
+
+ /**
+ * Beginning with element at the index corresponding to the value of the
+ * <code>startIndx</code> parameter, parses the elements contained in
+ * the <code>args</code> parameter, which should contain the arguments
+ * input on the command line when requesting that a program be started.
+ * This method assumes a particular syntax and format for that command
+ * line (see this class' description for a complete description of the
+ * expected syntax).
+ * <p>
+ *
+ * @param args <code>String</code> array containing the arguments
+ * input to the command line.
+ * @param startIndx <code>int</code> value indicating the index of the
+ * element of the <code>args</code> parameter where
+ * parsing should begin.
+ *
+ * @return instance of the class <code>ParsedArgs</code>
+ * containing the values of the arguments that were parsed.
+ * Will return <code>null</code> if the arguments cannot be
+ * parsed for any reason (for example, the argument list format
+ * is invalid).
+ *
+ * @see ParsedArgs
+ */
+ public ParsedArgs parseArgs(String[] args, int startIndx) {
+ if (args == null)
+ return null;
+ boolean argsValid = true;
+ /* Parse the remaining arguments, looking for groups, locators, etc. */
+ String[] groups = defaultGroups;
+ LookupLocator[] locators = new LookupLocator[]{};
+ String javaProgram = null;
+ String sharedvm_log = null;
+ Properties properties = null;
+ String[] options = null;
+ ArrayList groupList = new ArrayList();
+ ArrayList locatorList = new ArrayList();
+ ArrayList propertyList = new ArrayList();
+ ArrayList optionList = new ArrayList();
+
+ for(int i=startIndx;i<args.length; ) {
+ if (dbgParse != null) {
+ dbgParse.println("StartUtil::parseArgs: parsing arg["
+ + i + "]: " + args[i]);
+ }
+ if(isClasspath(args[i])) {
+ if(args.length <= (i+1)) {
+ print("classpath.invalid", null);
+ argsValid = false;
+ break;
+ }
+ if (sharedvm_log != null) {
+ print("java_opts.incompatible", args[i]);
+ argsValid = false;
+ break;
+ }
+ optionList.add(args[i]);
+ optionList.add(args[i+1]);
+ i = i+2; //step over -classpath and arg just set
+ continue;
+ }//endif(-classpath arg)
+ if(isOption(args[i])) {
+ if (sharedvm_log != null) {
+ print("java_opts.incompatible", args[i]);
+ argsValid = false;
+ break;
+ }
+ optionList.add(args[i]);
+ i = i+1; //step over arg just set
+ continue;
+ }//endif(-Xdebug -verbose)
+ if(isProperty(args[i])) {
+ if (sharedvm_log != null) {
+ print("java_props.incompatible", args[i]);
+ argsValid = false;
+ break;
+ }
+ propertyList.add(args[i]);
+ i = i+1; //step over arg just set
+ continue;
+ }//endif(-DpropKey0.propKey1.propKey2=propertyValue)
+ if(isSharedGroupLog(args[i])) {
+ if (javaProgram != null ||
+ propertyList.size() > 0 ||
+ optionList.size() > 0) {
+ print("sharedvm_log.incompatible", args[i]);
+ argsValid = false;
+ break;
+ }
+ sharedvm_log = args[i];
+ i = i+1;
+ continue;
+ }//endif(/dir0/dir1/dir2/<cookie>)
+ if(isProgram(args[i])) {
+ if (sharedvm_log != null) {
+ print("java_prog.incompatible", args[i]);
+ argsValid = false;
+ break;
+ }
+ javaProgram = args[i];
+ i = i+1; //step over arg just set
+ continue;
+ }//endif(/dir0/dir1/dir2/javaProgramToExecute)
+ LookupLocator loc = getLocator(args[i]); // for a singleton locator
+ if(loc != null) {
+ locatorList.add(loc);
+ i = i+1; //step over arg just set
+ continue;
+ }//endif(jini://host:[port])
+ if(isCommaSeparatedList(args[i])) {
+ String[] grps = getGroupsFromCommaSeparatedList(args[i]);
+ /* If groups has already been set to ALL_GROUPS because of
+ * some other argument, that value takes precedence
+ */
+ if(groups != DiscoveryGroupManagement.ALL_GROUPS) {
+ /* If grps is NO_GROUPS, that takes precedence over all
+ * other groups, except ALL_GROUPS
+ */
+ if( (grps == DiscoveryGroupManagement.ALL_GROUPS)) {
+ groups = DiscoveryGroupManagement.ALL_GROUPS;
+ } else if( (grps == DiscoveryGroupManagement.NO_GROUPS)) {
+ groups = DiscoveryGroupManagement.NO_GROUPS;
+ } else { //add the groups found to the current ArrayList
+ for(int j=0;j<grps.length;j++) {
+ groupList.add(grps[j]);
+ }
+ }
+ }//endif(groups != ALL_GROUPS)
+ LookupLocator[] locs
+ = getLocatorsFromCommaSeparatedList(args[i]);
+ for(int j=0;j<locs.length;j++) {
+ locatorList.add(locs[j]);
+ }
+ i = i+1; //step over the single arg just processed
+ continue;
+ }//endif(g0,jini://host0,g1,jini://host1:port,g2)
+ if( (args[i].equals("-groups")) || (args[i].equals("-group")) ) {
+ if((i+1) == args.length) {
+ print("groups.invalid", null);
+ argsValid = false;
+ break;
+ }
+ int srcOffset = i+1;
+ int count = args.length - srcOffset;
+ String[] dst = new String[count];
+ System.arraycopy(args, srcOffset, dst, 0, count);
+ ParsedListResult grpsResult = parseGroupList(dst);
+ for(int j=0;j<(grpsResult.extractedArgs).length;j++) {
+ groupList.add(grpsResult.extractedArgs[j]);
+ }
+ i = i+grpsResult.nArgsParsed+1; //step over the arg SET
+ continue;
+ }//endif(-groups g0 g1 g2)
+ if( (args[i].equals("-locators")) || (args[i].equals("-locs"))
+ || (args[i].equals("-locator")) || (args[i].equals("-loc")) )
+ {
+ if((i+1) == args.length) {
+ print("locators.invalid", null);
+ argsValid = false;
+ break;
+ }
+ int srcOffset = i+1;
+ int count = args.length - srcOffset;
+ String[] dst = new String[count];
+ System.arraycopy(args, srcOffset, dst, 0, count);
+ ParsedListResult locsResult = parseLocatorList(dst);
+ for(int j=0;j<(locsResult.extractedArgs).length;j++) {
+ locatorList.add(locsResult.extractedArgs[j]);
+ }
+ i = i+locsResult.nArgsParsed+1; //step over the arg SET
+ continue;
+ }//endif(-locators host0 host1 host2)
+
+ /* If the current argument satisfies none of the above
+ * characteristics, assume it must be a group name
+ */
+ if(groups != DiscoveryGroupManagement.ALL_GROUPS) {
+ /* If args[i] is NO_GROUPS, that takes precedence over all
+ * other groups, except ALL_GROUPS
+ */
+ if(args[i].equals(getString("groups.all"))) {
+ groups = DiscoveryGroupManagement.ALL_GROUPS;
+ } else if(args[i].equals(getString("groups.none"))) {
+ groups = DiscoveryGroupManagement.NO_GROUPS;
+ } else if(args[i].equals(getString("groups.public"))) {
+ groupList.add("");
+ } else { //add the group found to the current ArrayList
+ groupList.add(args[i]);
+ }
+ i = i+1; //step over the single arg just processed
+ continue;
+ }//endif(groups != ALL_GROUPS)
+ print("parse.unprocessed_args", args[i]);
+ argsValid = false; // don't ignore
+ break;
+ // i = i+1; //step over arg just set
+ }//end loop(i)
+
+ if(!argsValid) return null;
+
+ /* Prepare the groups for return */
+ if(!groupList.isEmpty()) { //arg list had at least 1 group
+ groups = (String[])(groupList.toArray
+ (new String[groupList.size()]));
+ }
+ /* Prepare the locators for return */
+ if(!locatorList.isEmpty()) { //arg list had at least 1 locator
+ locators = (LookupLocator[])(locatorList.toArray
+ (new LookupLocator[locatorList.size()]));
+ /* If arg list had only locators, then re-set groups = NO_GROUPS */
+ if( groupList.isEmpty()
+ && groups != DiscoveryGroupManagement.ALL_GROUPS ) {
+ groups = DiscoveryGroupManagement.NO_GROUPS;
+ }
+ }
+ /* Prepare the properties for return */
+ if(!propertyList.isEmpty()) {
+ properties = new Properties();
+ for(int i=0;i<propertyList.size();i++) {
+ String prop = (String)(propertyList.get(i));
+ int k = prop.indexOf("=");
+ if (k < 0) {
+ properties.put(prop.substring(2), "");
+ } else {
+ properties.put(prop.substring(2, k), // property key
+ prop.substring(k + 1));//property value
+ }
+ }
+ }
+ /* Prepare the options for return */
+ if(!optionList.isEmpty()) {
+ options = (String[])(optionList.toArray
+ (new String[optionList.size()]));
+ }
+
+ ParsedArgs procArgs =
+ new ParsedArgs(null,null,null,
+ groups,
+ locators,
+ javaProgram,
+ properties,
+ options,
+ sharedvm_log);
+
+ if (dbgParse != null) {
+ dbgParse.println("StartUtil::parseArgs: "
+ + "returning processed args ...");
+ printParsedArgs(procArgs);
+ }
+ return procArgs;
+ }//end parseArgs
+
+ /**
+ * Parses the elements contained in the <code>args</code> parameter,
+ * which should contain the arguments input on the command line
+ * when requesting that a program be started. This method assumes a
+ * particular syntax and format for that command line: that of an
+ * activatable service.
+ * <p>
+ *
+ * @param args <code>String</code> array containing the arguments input
+ * to the command line
+ *
+ * @return instance of the class <code>ParsedArgs</code>
+ * containing the values of the arguments that were parsed.
+ * Will return <code>null</code> if the arguments cannot be
+ * parsed for any reason (for example, the argument list format
+ * is invalid).
+ *
+ * @see ParsedArgs
+ */
+ public ParsedArgs parseActivatableArgs(String[] args) {
+ if( (args == null) || (args.length < 3) ) return null;
+ String codebase = args[0];
+ String policyFile = getPolicyFile(args[1]);
+ String logDir = getLogDirectory(args[2]);
+ if( (!isValidCodebaseUrl(codebase))
+ || (policyFile == null) || (logDir == null) ) return null;
+ ParsedArgs parsedArgs = parseArgs(args,3);
+ if (parsedArgs == null)
+ return null;
+ return new ParsedArgs(codebase,
+ policyFile,
+ logDir,
+ parsedArgs.getGroups(),
+ parsedArgs.getLocators(),
+ parsedArgs.getJavaProgram(),
+ parsedArgs.getProperties(),
+ parsedArgs.getOptions(),
+ parsedArgs.getSharedVMLog());
+ }//end parseActivatableArgs
+
+ /**
+ * Parses the elements contained in the <code>args</code> parameter,
+ * which should contain the arguments input on the command line
+ * when requesting that a program be started. This method assumes a
+ * particular syntax and format for that command line: that of a
+ * transient service.
+ * <p>
+ *
+ * @param args <code>String</code> array containing the arguments input
+ * to the command line
+ *
+ * @return instance of the class <code>ParsedArgs</code>
+ * containing the values of the arguments that were parsed.
+ * Will return <code>null</code> if the arguments cannot be
+ * parsed for any reason (for example, the argument list format
+ * is invalid).
+ *
+ * @see ParsedArgs
+ */
+ public ParsedArgs parseTransientArgs(String[] args) {
+ if( (args == null) || (args.length < 1) ) return null;
+ /* Verify logDir does not already exist and get the absolute path */
+ String logDir = getLogDirectory(args[0]);
+ if(logDir == null) return null;
+ ParsedArgs parsedArgs = parseArgs(args,1);
+ if (parsedArgs == null)
+ return null;
+ return new ParsedArgs(null, //codebase,
+ null, //policyFile,
+ logDir,
+ parsedArgs.getGroups(),
+ parsedArgs.getLocators(),
+ parsedArgs.getJavaProgram(),
+ parsedArgs.getProperties(),
+ parsedArgs.getOptions());
+ }//end parseTransientArgs
+
+ /** Prints a general usage message extracted from the resource bundle */
+ public void printUsage() {
+ print("usage", null);
+ print("groups.usage", null);
+ print("locators.usage", null);
+ print("javaprog.usage", null);
+ print("properties.usage", null);
+ print("options.usage", null);
+ print("sharedvm.usage", null);
+ }//end printUsage
+
+ /** Prints a usage message, specific to a transient service, extracted
+ * from the resource bundle
+ */
+ public void printTransientUsage() {
+ print("transient.usage", null);
+ print("groups.usage", null);
+ print("locators.usage", null);
+ }//end printTransientUsage
+
+ /** Prints a usage message, specific to a transient, non-persistent
+ * service, extracted from the resource bundle
+ */
+ public void printNonPersistentUsage() {
+ print("nonpersistent.usage", null);
+ print("groups.usage", null);
+ print("locators.usage", null);
+ }//end printTransientUsage
+
+ /**
+ * Displays the resource String corresponding to a particular key, but
+ * with a given value substituted in the appropriate location in the
+ * String.
+ *
+ * @param resourceKey a non-null case-sensitive String containing the
+ * suffix identifier that, together with the
+ * resourceName, make up the resource whose String
+ * is to be printed.
+ * <p>
+ * For example, if a resource stored in the resource
+ * bundle is identified by a key such as
+ * "service.activation.notUp", then the component
+ * of the key referred to as the resourceName of
+ * the resource is the prefix substring "service".
+ * Similarly, the component referred to as the
+ * resourceKey of the resource is the suffix substring
+ * that appears immediately after the period which
+ * follows the resourceName; "activation.notUp" in
+ * this case.
+ * <p>
+ * Thus, if it is desired that the string associated
+ * with a particular resource be printed by this
+ * method, then only the resourceKey component, not
+ * the whole key itself, need be input to this method;
+ * "activation.notUp" in the example above. The
+ * resourceName (which is initialized when this
+ * class is constructed) will be pre-pended so that
+ * the correct key is used when retrieving the string
+ * value from the resource bundle.
+ * @param val the value to substitute in the resource String
+ * before displaying
+ */
+ public void print(String resourceKey, String val) {
+ String fmt = getString(resourceKey);
+ String key = resourceName+"."+resourceKey;
+ if (fmt == null)
+ fmt = "no text found: \"" + key + "\" {0}";
+ System.out.println(MessageFormat.format(fmt, new String[]{val}));
+ }//end print
+
+ /**
+ * Displays the contents of each field of the input parameter. Useful
+ * for debugging.
+ *
+ * @param parsedArgs data structure containing values of arguments input
+ * to the command line and parsed prior to invoking
+ * this method
+ */
+ public static void printParsedArgs(ParsedArgs parsedArgs) {
+ System.out.println("codebase = "+parsedArgs.getCodebase());
+ System.out.println("policyFile = "+parsedArgs.getPolicyFile());
+ System.out.println("logDir = "+parsedArgs.getLogDir());
+ System.out.println("SharedVMLog = "+parsedArgs.getSharedVMLog());
+
+ String[] groups = parsedArgs.getGroups();
+ if(groups == DiscoveryGroupManagement.ALL_GROUPS) {
+ System.out.println("groups = ALL_GROUPS");
+ }else if(groups.length == 0){
+ System.out.println("groups = NO_GROUPS");
+ }else{
+ for(int i=0;i<groups.length;i++) {
+ if(groups[i].equals("")) {
+ System.out.println(" groups["+i+"] = The PUBLIC Group");
+ } else {
+ System.out.println(" groups["+i+"] = "+groups[i]);
+ }
+ }//end loop
+ }//endif(groups)
+
+ LookupLocator[] locators = parsedArgs.getLocators();
+ if(locators == null) {
+ System.out.println("locators = null");
+ }else if(locators.length == 0){
+ System.out.println("locators = NO_LOCATORS");
+ }else{
+ for(int i=0;i<locators.length;i++) {
+ System.out.println(" locators["+i+"] = "+locators[i]);
+ }//end loop
+ }//endif(locators)
+
+ System.out.println("javaProgram = "+parsedArgs.getJavaProgram());
+ Properties properties = parsedArgs.getProperties();
+ if(properties == null) {
+ System.out.println("properties = null");
+ }else {
+ properties.list(System.out);
+ }//endif
+
+ String[] options = parsedArgs.getOptions();
+ if(options == null) {
+ System.out.println("options = null");
+ }else {
+ for(int k=0;k<options.length;k++) {
+ System.out.println(" options["+k+"] = "+options[k]);
+ }//end loop
+ }//endif
+ }//end printParsedArgs
+
+ /**
+ * Retrieves a String resource corresponding to a particular key from the
+ * resource bundle. If the resource bundle does not yet exist, this
+ * method will first load and instantiate the resource bundle.
+ *
+ * @param resourceKey a non-null case-sensitive String containing the
+ * suffix identifier that, together with the
+ * resourceName, make up the resource whose String
+ * is to be retrieved.
+ * <p>
+ * For example, if a resource stored in the resource
+ * bundle is identified by a key such as
+ * "service.activation.notUp", then the component
+ * of the key referred to as the resourceName of
+ * the resource is the prefix substring "service".
+ * Similarly, the component referred to as the
+ * resourceKey of the resource is the suffix substring
+ * that appears immediately after the period which
+ * follows the resourceName; "activation.notUp" in
+ * this case.
+ * <p>
+ * Thus, if it is desired that the string associated
+ * with a particular resource be retrieved by this
+ * method, then only the resourceKey component, not
+ * the whole key itself, need be input to this method;
+ * "activation.notUp" in the example above. The
+ * resourceName (which is initialized when this
+ * class is constructed) will be pre-pended so that
+ * the correct key is used when retrieving the string
+ * value from the resource bundle.
+ *
+ * @return a non-null String containing the value of the desired resource
+ */
+ private String getString(String resourceKey) {
+ String key = resourceName+"."+resourceKey;
+ try {
+ return resources.getString(key);
+ } catch (MissingResourceException e) {
+ return null;
+ }
+ }//end getString
+
+ /**
+ * Retrieves a formatted String resource corresponding to a particular
+ * key from the resource bundle. If the resource bundle does not yet
+ * exist, this method will first load and instantiate the resource bundle.
+ *
+ * @param resourceKey a non-null case-sensitive String containing the
+ * suffix identifier that, together with the
+ * resourceName, make up the resource whose String
+ * is to be retrieved.
+ * <p>
+ * For example, if a resource stored in the resource
+ * bundle is identified by a key such as
+ * "service.activation.notUp", then the component
+ * of the key referred to as the resourceName of
+ * the resource is the prefix substring "service".
+ * Similarly, the component referred to as the
+ * resourceKey of the resource is the suffix substring
+ * that appears immediately after the period which
+ * follows the resourceName; "activation.notUp" in
+ * this case.
+ * <p>
+ * Thus, if it is desired that the string associated
+ * with a particular resource be retrieved by this
+ * method, then only the resourceKey component, not
+ * the whole key itself, need be input to this method;
+ * "activation.notUp" in the example above. The
+ * resourceName (which is initialized when this
+ * class is constructed) will be pre-pended so that
+ * the correct key is used when retrieving the string
+ * value from the resource bundle.
+ * @param val the value to substitute in the resource String
+ * when formatting
+ *
+ * @return a non-null String containing the formatted value of the
+ * desired resource
+ */
+ public String getString(String resourceKey, String val) {
+ String fmt = getString(resourceKey);
+ String key = resourceName+"."+resourceKey;
+ if (fmt == null)
+ fmt = "no text found: \"" + key + "\" {0}";
+ return (MessageFormat.format(fmt, new String[]{val}));
+ }//end getString
+
+ /** Determines if the input String is a valid URL */
+ private boolean isValidCodebaseUrl(String str) {
+ return isValidCodebaseUrl(str,true);
+ }//end isValidCodebaseUrl
+
+ /** Determines if the input String is a valid URL.
+ * <p>
+ * If <code>true</code> is input to the <code>notify</code> parameter,
+ * then this method will print a diagnostic message; otherwise this
+ * method simply tests if the input String is a valid URL, and returns
+ * the appropriate boolean value.
+ */
+ private boolean isValidCodebaseUrl(String str, boolean notify) {
+ boolean codebaseValid = true;
+ StringTokenizer st = new StringTokenizer(str," \"");
+ for (int i = 0; st.hasMoreTokens(); i++) {
+ String url = st.nextToken();
+ if (!url.endsWith("/") &&
+ !url.endsWith(".jar") && !url.endsWith(".zip"))
+ {
+ if(!notify) return false;
+ print("codebase.slash", url);
+ codebaseValid = false;
+ }
+ try {
+ new URL(url);
+ } catch (MalformedURLException e) {
+ if(!notify) return false;
+ print("codebase.syntax", url);
+ codebaseValid = false;
+ }
+ }
+ return codebaseValid;
+ }//end isValidCodebaseUrl
+
+ /** Determines if the input String corresponds to an existing file */
+ private boolean isValidPolicyFile(String filename) {
+ return isValidPolicyFile(filename,true);
+ }//end isValidPolicyFile
+
+ /** Determines if the input String corresponds to an existing file.
+ * <p>
+ * If <code>true</code> is input to the <code>notify</code> parameter,
+ * then this method will print a diagnostic message; otherwise this
+ * method simply tests if the input String corresponds to an existing
+ * file, and returns the appropriate boolean value.
+ */
+ private boolean isValidPolicyFile(String filename, boolean notify) {
+ File pf = new File(filename);
+ if (!pf.exists()) {
+ if(!notify) return false;
+ print("policy.exist", filename);
+ return false;
+ }
+ return true;
+ }//end isValidPolicyFile
+
+ /** Determines if the input String corresponds to an existing file and
+ * returns the absolute path to the file.
+ */
+ private String getPolicyFile(String filename) {
+ return getPolicyFile(filename,true);
+ }//end getPolicyFile
+
+ /** Determines if the input String corresponds to an existing file and
+ * returns the absolute path to the file.
+ * <p>
+ * If <code>true</code> is input to the <code>notify</code> parameter,
+ * then this method will print a diagnostic message; otherwise this
+ * method simply tests if the input String corresponds to an existing
+ * file, and returns the absolute path to the file.
+ */
+ private String getPolicyFile(String filename, boolean notify) {
+ if(!isValidPolicyFile(filename,notify)) return null;
+ String absDirPath = new String(filename);
+ File df = new File(absDirPath);
+ if (!df.isAbsolute()) {
+ absDirPath = df.getAbsolutePath();
+ print("policy.abs", absDirPath);
+ }
+ return absDirPath;
+ }//end getPolicyFile
+
+ /**
+ * Determines if the input String is a valid shared group log directory.
+ * A valid log directory is one that contains a well known cookie file,
+ * defined by <code>GroupConstants.GROUP_COOKIE_FILE</code>, that is also
+ * readable.
+ */
+ private boolean isSharedGroupLog(String dirPath) {
+ if(!canTestForFile(dirPath))
+ return false;
+ File cookie = new File(dirPath, GroupConstants.GROUP_COOKIE_FILE);
+ return (cookie.exists() && cookie.isFile());
+ }//end isSharedGroupLog
+
+ /** Determines if the input String can be used as a log directory.
+ * <p>
+ * If <code>true</code> is input to the <code>notify</code> parameter,
+ * then this method will print a diagnostic message; otherwise this
+ * method simply tests if the input String can be used as a log
+ * directory, and returns the appropriate boolean value.
+ */
+ private boolean isValidLogDirectory(String dirPath, boolean notify) {
+ File df = new File(dirPath);
+ if (df.exists()) { //if it already exists, can't use it
+ if(!notify) return false;
+ print("logdir.exist", dirPath);
+ return false;
+ } else if( (isValidCodebaseUrl(dirPath,false))
+ || (isValidPolicyFile(dirPath,false))
+ || (isClasspath(dirPath))
+ || (isOption(dirPath))
+ || (isProperty(dirPath))
+ || (isProgram(dirPath))
+ || (isCommaSeparatedList(dirPath)) )
+ {
+ if(!notify) return false;
+ print("logdir.invalid", dirPath);
+ return false;
+ }//endif
+ return true;
+ }//end isValidLogDirectory
+
+ /** Determines if the input String can be used as a log directory,
+ * and returns the absolute path of the directory.
+ */
+ private String getLogDirectory(String dirPath) {
+ return getLogDirectory(dirPath,true);
+ }//end getLogDirectory
+
+ /** Determines if the input String can be used as a log directory,
+ * and returns the absolute path of the directory.
+ * <p>
+ * If <code>true</code> is input to the <code>notify</code> parameter,
+ * then this method will print a diagnostic message; otherwise this
+ * method simply tests if the input String can be used as a log
+ * directory, and returns the absolute path of the directory.
+ */
+ private String getLogDirectory(String dirPath, boolean notify) {
+ if(!isValidLogDirectory(dirPath,notify)) return null;
+ String absDirPath = new String(dirPath);
+ File df = new File(absDirPath);
+ if (!df.isAbsolute()) {
+ absDirPath = df.getAbsolutePath();
+ if(notify)
+ print("logdir.abs", absDirPath);
+ }
+ return absDirPath;
+ }//end getLogDirectory
+
+ /** Determines if the input String represents a classpath identifier */
+ private static boolean isClasspath(String arg) {
+ if( (arg.equals("-classpath")) || (arg.equals("-cp")) ) return true;
+ return false;
+ }//end isClasspath
+
+ /** Determines if the input String represents a valid java option */
+ private static boolean isOption(String arg) {
+ /* This method considers the input an option if it begins with
+ * sub-strings such as: "-C-D", "-J-D", "-verbose", "-X", etc.;
+ * that is, anything that begins with a "-" that is not "-classpath",
+ * "-cp", or "-D" and does not start with -group(s) or -loc(ators)
+ */
+ if( (arg.startsWith("-"))
+ && !( (arg.equals("-classpath")) || (arg.equals("-cp"))
+ || (arg.startsWith("-groups")) || (arg.startsWith("-group"))
+ || (arg.startsWith("-locators")) || (arg.startsWith("-locs"))
+ || (arg.startsWith("-locator")) || (arg.startsWith("-loc"))
+ || (arg.startsWith("-D"))
+ )
+ )
+ {
+ return true;
+ }
+ return false;
+ }//end isOption
+
+ /** Determines if the input String represents a valid java property */
+ private static boolean isProperty(String arg) {
+ return arg.startsWith("-D");
+ }//end isProperty
+
+ /** Determines if the input String can be used as a program. */
+ private static boolean isProgram(String arg) {
+ /* If the argument doesn't begin with '-', isn't a group name
+ * (doesn't contain a file separator), isn't a locator (is not a
+ * valid Jini(TM) URL), exists as a file -- not a directory, and
+ * the absolute path of the file is given (that is, the argument
+ * begins with a file separator such as '/' or 'drive:\') then
+ * this method assumes the given argument is a program to be executed.
+ */
+ if( !canTestForFile(arg) ) return false;
+ File fd = new File(arg);
+ if( (fd.exists()) && !(fd.isDirectory()) && (fd.isAbsolute()) ) {
+ return true;
+ }
+ return false;
+ }//end isProgram
+
+ /** Instantiates a LookupLocator using the input String */
+ private static LookupLocator getLocator(String str) {
+ if(isCommaSeparatedList(str)) return null; //commas in URL not allowed
+ try {
+ return new LookupLocator(str);
+ } catch(MalformedURLException e) {
+ return null;
+ }
+ }//end getLocator
+
+ /** Instantiates a LookupLocator using the input hostname and the
+ * default port number
+ */
+ private static LookupLocator hostToLocator(String hostname) {
+ try {
+ return new LookupLocator("jini://"+hostname+":4160/");
+ } catch(MalformedURLException e) {
+ return null;
+ }
+ }//end hostToLocator
+
+ /** Determines if the input String is delimited by commas */
+ private static boolean isCommaSeparatedList(String arg) {
+ /* If arg contains 'comma(s)', return true */
+ if(arg.indexOf(",") >= 0) return true;
+ return false;
+ }//end isCommaSeparatedList
+
+ /** Determines if the input <code>String</code> is "valid"; that is,
+ * determines if the input <code>String</code> is not a property,
+ * a comma separated list,
+ * or a <code>LookupLocator</code> so that when input to the various
+ * <code>File</code> methods, a <code>SecurityException</code> will
+ * not occur.
+ *
+ * This method interprets the input argument as being valid only if
+ * the input argument is:
+ * <p><ul>
+ * <li> not a property or option (does not begin with a '-')
+ * <li> not a comma-separated list of groups and/or locators
+ * <li> not a <code>LookupLocator</code> (is not a valid Jini URL)
+ * <li> will not result in a <code>SecurityException</code> when
+ * tested for file existence
+ * </ul><p>
+ * This is important
+ * because the call to <code>File.exists</code> will result in a
+ * <code>SecurityException</code> if read permission is not granted for
+ * the input argument (ex. a <code>LookupLocator</code> <code>URL</code>).
+ * In order to avoid having to
+ * grant wide read permissions, methods which need to determine if a
+ * <code>String</code> is a valid file (ex. <code>isProgram</code> or
+ * <code>isValidPolicy</code>) can invoke this method and decide not
+ * to continue processing the given <code>String</code> that is found
+ * to be a locator.
+ *
+ * @return <code>true</code> if the argument doesn't begin with '-',
+ * isn't a comma-separated list of groups and/or locators,
+ * isn't a
+ * locator (is not a valid Jini URL), and does not result in
+ * a <code>SecurityException</code> when tested for file
+ * existence; <code>false</code> otherwise.
+ */
+ private static boolean canTestForFile(String arg) {
+ if(arg.startsWith("-")) return false; //is a property or option
+ if(isCommaSeparatedList(arg)) return false; //is a comma-separated list
+ if(getLocator(arg) != null) return false; //is a valid Jini URL
+ try {
+ (new File(arg)).exists();//determine if a SecurityException occurs
+ return true;
+ } catch(SecurityException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }//end canTestForFile
+
+ /** Parses a comma-separated String, extracting the sub-strings that
+ * represent group names (sub-strings NOT in the jini URL format)
+ */
+ private String[] getGroupsFromCommaSeparatedList(String list) {
+ /* If the list contains "none" or "all", those override all other
+ * groups. If the list contains both "none" and "all", "all"
+ * takes precedence over "none". Additionally, if the group name
+ * "public" is input, it will be returned as the 'un-named public
+ * group' ("").
+ */
+ if(list.startsWith("-loc")) return DiscoveryGroupManagement.NO_GROUPS;
+ String lst = list;
+ if(list.startsWith("-group")) {//strip off -group,-groups
+ int offset = list.indexOf(",");
+ lst = list.substring(offset+1);
+ }
+ String publicGroup = getString("groups.public");
+ String noGroups = getString("groups.none");
+ String allGroups = getString("groups.all");
+ boolean groupsNone = false;
+ boolean containsLocs = false;
+ StringTokenizer st = new StringTokenizer(lst, " \t\n\r\f,");
+ int n = st.countTokens();
+ if (n > 0) {
+ ArrayList grpList = new ArrayList();
+ for (int i=0; st.hasMoreTokens(); i++) {
+ String group = st.nextToken();
+ if (getLocator(group) != null) {//skip locator urls
+ containsLocs = true;
+ continue;
+ } else if (group.equals(publicGroup)) {
+ group = "";
+ } else if(group.equals(noGroups)) { //overrides other groups
+ groupsNone = true;
+ } else if(group.equals(allGroups)) {//overrides everything
+ return DiscoveryGroupManagement.ALL_GROUPS;
+ }
+ grpList.add(group);
+ }//end loop
+ /* If 'none' or only locators were input, then return NO_GROUPS */
+ if( groupsNone || (containsLocs && (grpList.size() == 0)) ) {
+ return DiscoveryGroupManagement.NO_GROUPS;
+ }
+ return ((String[])(grpList.toArray(new String[grpList.size()])));
+ }//end if
+ return defaultGroups;
+ }//end getGroupsFromCommaSeparatedList
+
+ /** Parses a comma-separated String, extracting the sub-strings that
+ * are given in the jini URL format (jini://hostname:[port])
+ */
+ private static LookupLocator[] getLocatorsFromCommaSeparatedList
+ (String list)
+ {
+ if(list.startsWith("-group")) return new LookupLocator[0];
+ String lst = list;
+ boolean assumeAllAreLocs = false;
+ if(list.startsWith("-loc")) {//strip off -loc,-locs,-locator,-locators
+ int offset = list.indexOf(",");
+ lst = list.substring(offset+1);
+ assumeAllAreLocs = true;
+ }
+ StringTokenizer st = new StringTokenizer(lst, " \t\n\r\f,");
+ int n = st.countTokens();
+ if (n > 0) {
+ ArrayList locList = new ArrayList();
+ for (int i=0; st.hasMoreTokens(); i++) {
+ String locStr = st.nextToken();
+ LookupLocator loc = getLocator(locStr);
+ if(loc != null) {
+ locList.add(loc);
+ } else {
+ if(assumeAllAreLocs) {
+ loc = hostToLocator(locStr);
+ if(loc != null) {
+ locList.add(loc);
+ }
+ }
+ }
+ }//end loop
+ return ((LookupLocator[])(locList.toArray
+ (new LookupLocator[locList.size()])));
+ }//end if
+ return new LookupLocator[0];
+ }//end getLocatorsFromCommaSeparatedList
+
+ /** Examines a String array, extracting the elements that that
+ * represent group names (elements NOT in the jini URL format)
+ */
+ private static ParsedListResult parseGroupList(String[] subArgs) {
+ ArrayList grpList = new ArrayList();
+ int nParsed = 0;
+ for(int i=0;i<subArgs.length;i++) {
+ if(subArgs[i].startsWith("-")) break;
+ if(isClasspath(subArgs[i])) break;
+ if(isOption(subArgs[i])) break;
+ if(isProperty(subArgs[i])) break;
+ if(isProgram(subArgs[i])) break;
+ LookupLocator loc = getLocator(subArgs[i]);
+ if(loc == null) grpList.add(subArgs[i]);
+ nParsed = nParsed+1;
+ }
+ String[] groups = (String[])(grpList.toArray
+ (new String[grpList.size()]));
+ return new ParsedListResult(nParsed,groups);
+ }//end parseGroupList
+
+ /** Examines a String array, extracting the elements that are given in
+ * the jini URL format (jini://hostname:[port])
+ */
+ private static ParsedListResult parseLocatorList(String[] subArgs) {
+ ArrayList locList = new ArrayList();
+ int nParsed = 0;
+ for(int i=0;i<subArgs.length;i++) {
+ if(subArgs[i].startsWith("-")) break;
+ if(isClasspath(subArgs[i])) break;
+ if(isOption(subArgs[i])) break;
+ if(isProperty(subArgs[i])) break;
+ if(isProgram(subArgs[i])) break;
+ LookupLocator loc = getLocator(subArgs[i]);
+ if(loc != null) {
+ locList.add(loc);
+ } else {
+ loc = hostToLocator(subArgs[i]);
+ if(loc != null) {
+ locList.add(loc);
+ }
+ }
+ nParsed = nParsed+1;
+ }
+ LookupLocator[] locators = (LookupLocator[])(locList.toArray
+ (new LookupLocator[locList.size()]));
+ return new ParsedListResult(nParsed,locators);
+ }//end parseLocatorList
+
+ /** Determines if the given String is a valid 'http', 'ftp', or 'file'
+ * URL
+ */
+ private static boolean isUrl(String str) {
+ try {
+ URL url = new URL(str);
+ String protocol = url.getProtocol();
+ if( protocol.equals("http") ) return true;
+ if( protocol.equals("ftp") ) return true;
+ if( protocol.equals("file") ) return true;
+ return false;
+ } catch(MalformedURLException e) {
+ return false;
+ }
+ }//end isUrl
+
+}//end class StartUtil
Propchange: river/tck/src/com/sun/jini/compat/start/StartUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/test/AnnouncementResponseTest.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/test/AnnouncementResponseTest.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/test/AnnouncementResponseTest.java (added)
+++ river/tck/src/com/sun/jini/compat/test/AnnouncementResponseTest.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,297 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.test;
+
+import java.rmi.RemoteException;
+
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.DatagramPacket;
+import java.net.UnknownHostException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+
+import com.sun.jini.compat.harness.Status;
+import com.sun.jini.compat.harness.DefaultTest;
+import com.sun.jini.compat.harness.BasicAdmin;
+import com.sun.jini.compat.harness.BasicServiceAdmin;
+import com.sun.jini.compat.harness.Config;
+import com.sun.jini.compat.harness.TestUtility;
+
+import net.jini.discovery.Constants;
+
+import net.jini.core.lookup.ServiceID;
+
+/**
+ * Tests whether a service responds to an announcement from a
+ * lookup service that it should respond to by connecting to
+ * the specified socket and sending a unicast request.
+ */
+public class AnnouncementResponseTest extends DefaultTest {
+
+ private BasicAdmin admin;
+ SocketThread st;
+ Socket sock;
+
+ /**
+ * Sets up a socket-listening thread that listens on the port
+ * specified in the announcement packet. The test then sends
+ * out properly formatted announcement packets in
+ * the appropriate multicast group and in the public lookup
+ * service group every second up to the failureTime. If
+ * the service connects to the socket and sends a unicast
+ * request packet, the test decodes the packet and checks
+ * its formatting. If the service doesn't connect to the socket
+ * within the failureTime, or sends an improperly formatted
+ * unicast request packet, the service fails.
+ *
+ * @param args Command line arguments passed through
+ * @return The status of this run (failed or passed
+ * and a comment)
+ */
+ public Status run(String[] args) {
+ Config conf = getConfig();
+ admin = conf.getAdmin();
+
+ try {
+ TestUtility.log(Config.ALL,"Test: starting program");
+ admin.start();
+ } catch (RemoteException re) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",re);
+ return Status.failed(Status.ENV,"Problem starting program");
+ }
+
+ try {
+ st = new SocketThread(conf.getFailureTime());
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.ENV,"Could not construct a "
+ + "ServerSocket");
+ }
+
+ MulticastSocket ms = null;
+ try {
+ TestUtility.log(Config.ALL,"Test: opening multicast "
+ + "announcement socket");
+ ms = new MulticastSocket(Constants.discoveryPort);
+ ms.joinGroup(Constants.getAnnouncementAddress());
+ ms.setSoTimeout(conf.getFailureTime());
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.ENV,"Could not construct or "
+ + "configure a MulticastSocket");
+ }
+
+ DatagramPacket sendPacket = null;
+ try {
+ TestUtility.log(Config.ALL,"Test: creating lookup announcement "
+ + "containing host and port: "
+ + InetAddress.getLocalHost().getHostAddress() + ":"
+ + st.getServerSocketPort());
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ DataOutputStream dataOut = new DataOutputStream(byteOut);
+ ServiceID sid = new ServiceID(42l, 42l);
+ dataOut.writeInt(1);
+ dataOut.writeUTF(InetAddress.getLocalHost().getHostAddress());
+ dataOut.writeInt(st.getServerSocketPort());
+ sid.writeBytes(dataOut);
+ dataOut.writeInt(1);
+ dataOut.writeUTF("");
+
+ byte[] buf = byteOut.toByteArray();
+ sendPacket = new DatagramPacket(buf, buf.length,
+ Constants.getAnnouncementAddress(),
+ Constants.discoveryPort);
+ } catch (UnknownHostException uhe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",uhe);
+ return Status.failed(Status.ENV,"Could not get local host "
+ + "address");
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.ENV,"Could not construct "
+ + "outgoing multicast announcement");
+ }
+
+ st.start();
+ long startTime = System.currentTimeMillis();
+ long duration = 0;
+ try {
+ synchronized(st) {
+ while ((sock == null) && (duration < conf.getFailureTime())) {
+ TestUtility.log(Config.ALL,"Test: sending announcement");
+ ms.send(sendPacket);
+ st.wait(1000);
+ TestUtility.log(Config.ALL,"Test: waiting for program "
+ + "to connect");
+ sock = st.getSocket();
+ duration = System.currentTimeMillis() - startTime;
+ }
+ }
+ ms.leaveGroup(Constants.getAnnouncementAddress());
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.ENV,"Could not send "
+ + "multicast announcement");
+ } catch (InterruptedException ie) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ie);
+ return Status.failed(Status.ENV,"Test interrupted");
+ }
+
+ if (sock == null) {
+ return Status.failed(Status.TEST, "Product did not "
+ + "respond to multicast announcement in "
+ + duration + " milliseconds");
+ }
+
+ try {
+ DataInputStream dis = new DataInputStream(sock.getInputStream());
+ TestUtility.log(Config.ALL,"Test: checking unicast request packet");
+ int protoVers = dis.readInt();
+ if (protoVers != 1) {
+ return Status.failed(Status.TEST, "Unicast request packet "
+ + "contains the wrong protocol number: " + protoVers);
+ }
+ } catch (EOFException eofe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",eofe);
+ return Status.failed(Status.TEST, "Unicast request packet "
+ + "ended unexpectedly");
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.TEST, "Unicast request packet "
+ + "improperly formatted");
+ }
+
+ return Status.passed("OK");
+ }
+
+ public void tearDown() {
+ super.tearDown();
+
+ if (st != null) {
+ st.interrupt();
+ }
+
+ try {
+ if (sock != null) {
+ sock.close();
+ }
+ } catch (IOException ignore) {}
+
+ try {
+ if (admin != null) {
+ TestUtility.log(Config.ALL,"Test: stopping program");
+ admin.stop();
+ }
+ } catch (RemoteException ignore) {}
+ }
+
+ private class SocketThread extends Thread {
+ private ServerSocket serv;
+ private Socket sock = null;
+ private boolean interrupted = false;
+
+ SocketThread(int socketTimeout) throws IOException {
+ super();
+ serv = new ServerSocket(0);
+ serv.setSoTimeout(socketTimeout);
+ }
+
+ /**
+ * Overrides Thread.interrupt(). This is a workaround for
+ * Thread.interrupt not working on
+ * ServerSocket.accept on all platforms.
+ */
+ public void interrupt() {
+ interrupted = true;
+ try {
+ serv.close();
+ } catch (IOException ignore) {}
+ }
+
+ /**
+ * Overrides Thread.isInterrupted().
+ */
+ public boolean isInterrupted() {
+ return interrupted;
+ }
+
+ public void run() {
+ Config conf = getConfig();
+ BasicAdmin ba = conf.getAdmin();
+ Socket tempSock;
+ while (!isInterrupted()) {
+ try {
+ tempSock = serv.accept();
+ if (!tempSock.getInetAddress().equals(ba.getAddress())) {
+ TestUtility.log(Config.ALL,"Test: ignoring socket "
+ + "connection from: " + tempSock.getInetAddress());
+ tempSock.close();
+ } else {
+ TestUtility.log(Config.ALL,"Test: "
+ + "got successful socket connection from: "
+ + tempSock.getInetAddress());
+ setSocket(tempSock);
+ break;
+ }
+ } catch (Exception ignore) {
+ TestUtility.log(Config.ERROR,"Test: "
+ + "ignoring the following exception from "
+ + "either accept, setSoTimeOut or getAddress:",ignore);
+ }
+ }
+
+ try {
+ serv.close();
+ } catch (IOException ignore) {}
+ }
+
+ private synchronized void setSocket(Socket s) {
+ sock = s;
+ notifyAll();
+ }
+
+ public int getServerSocketPort() {
+ return serv.getLocalPort();
+ }
+
+ public synchronized Socket getSocket() {
+ return sock;
+ }
+ }
+
+ public String[] getCategories() {
+ return (new String[] { BasicServiceAdmin.CATEGORY });
+ }
+
+ public Class[] getRequiredAdmins() {
+ return (new Class[] { BasicAdmin.class });
+ }
+
+ public String getDescription() {
+ return "AnnouncementResponseTest";
+ }
+
+}
+
Propchange: river/tck/src/com/sun/jini/compat/test/AnnouncementResponseTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/test/CodeDownloadTest.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/test/CodeDownloadTest.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/test/CodeDownloadTest.java (added)
+++ river/tck/src/com/sun/jini/compat/test/CodeDownloadTest.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,220 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.test;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.File;
+import java.net.InetAddress;
+
+import com.sun.jini.compat.harness.TestUtility;
+import com.sun.jini.compat.harness.Status;
+import com.sun.jini.compat.harness.DefaultTest;
+import com.sun.jini.compat.harness.BasicAdmin;
+import com.sun.jini.compat.harness.BasicClientAdmin;
+import com.sun.jini.compat.harness.BasicServiceAdmin;
+import com.sun.jini.compat.harness.Config;
+import com.sun.jini.compat.harness.DownloadEvent;
+import com.sun.jini.compat.harness.InstrumentedClassServer;
+import com.sun.jini.compat.harness.DownloadListener;
+
+import net.jini.core.lookup.ServiceRegistrar;
+
+/**
+ * Tests whether a service or a client downloads code from the
+ * java.rmi.server.codebase provided by the class server of the LDJ Kit.
+ * The code-base URL must use the HTTP protocol.
+ */
+public class CodeDownloadTest extends DefaultTest {
+
+ String randomName;
+ String tempJarFileName;
+ ServiceRegistrar lookup;
+ BasicAdmin admin;
+ InstrumentedClassServer ics;
+ CDListener cdl;
+
+ /**
+ * Copies the JAR file that contains the lookup service's
+ * downloadable code to a random file name. This new file is
+ * created to prevent caching from causing false negative
+ * results. The test then starts a lookup service with a
+ * codebase that points to the new file and registers a
+ * DownloadListener with the instrumented class server
+ * provided with the LDJ Kit. CodeDownloadTest then starts the
+ * program and waits for five times the failureTime. After
+ * either the wait times out or the test is notified,
+ * the test checks to see if the appropriate file (the
+ * randomly named file) was actually downloaded. The
+ * randomly named file is then deleted. If the randomly named file
+ * wasn't downloaded, the client or service being tested fails.
+ *
+ * @param args Command line arguments passed through
+ * @return The status of this run (failed or passed
+ * and a comment)
+ */
+ public Status run(String[] args) {
+ Config conf = getConfig();
+ cdl = new CDListener();
+ admin = conf.getAdmin();
+ ics = conf.getClassServer();
+ randomName = TestUtility.randomString(8) + ".jar";
+
+ try {
+ createTempJar();
+ } catch (IOException ioe) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ioe);
+ return Status.failed(Status.ENV,"Could not create a temporary "
+ + "copy of compat-lus-dl.jar");
+ }
+
+ try {
+ TestUtility.log(Config.ALL,"Test: starting lookup in public group");
+ lookup = TestUtility.startLookup(new String[] {""},
+ conf.getQuietTime(), "CodeDownloadTest_RegistrarLog",
+ randomName, conf);
+ } catch (Exception e) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",e);
+ return Status.failed(Status.ENV,"Problem starting lookup service");
+ }
+
+ try {
+ synchronized(cdl) {
+ ics.addDownloadListener(cdl);
+ TestUtility.log(Config.ALL,"Test: starting program");
+ admin.start();
+ long waitTime = 5 * conf.getFailureTime();
+ TestUtility.log(Config.ALL,"Test: waiting up to "
+ + waitTime + " milliseconds for code to be download");
+ cdl.wait(waitTime);
+ }
+ } catch (RemoteException re) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",re);
+ return Status.failed(Status.ENV,"Problem starting program");
+ } catch (InterruptedException ie) {
+ TestUtility.log(Config.ERROR,"Test: caught exception",ie);
+ return Status.failed(Status.ENV,"Test interrupted");
+ }
+
+ if (cdl.getFileName() == null) {
+ return Status.failed(Status.TEST, "Product never downloaded "
+ + "the lookup jar");
+ }
+
+ return Status.passed("OK");
+ }
+
+ public void tearDown() {
+ super.tearDown();
+
+ deleteTempJar();
+ ics.removeDownloadListener(cdl);
+ try {
+ if (lookup != null) {
+ TestUtility.log(Config.ALL,"Test: stopping lookup");
+ TestUtility.stopLookup(lookup, getConfig());
+ }
+ } catch (RemoteException ignore) {}
+ try {
+ if (admin != null) {
+ TestUtility.log(Config.ALL,"Test: stopping program");
+ admin.stop();
+ }
+ } catch (RemoteException ignore) {}
+ }
+
+ private class CDListener implements DownloadListener {
+
+ private String fname = null;
+
+ public synchronized String getFileName() {
+ return fname;
+ }
+
+ public synchronized void fileDownloaded(DownloadEvent de) {
+ String fileName = de.getName();
+ InetAddress address = de.getAddress();
+ Config conf = getConfig();
+ BasicAdmin ba = conf.getAdmin();
+ InetAddress ourAddr = null;
+
+ try {
+ ourAddr = ba.getAddress();
+ } catch(RemoteException re) {
+ TestUtility.log(Config.ERROR,"Test: <admin>.getAddress "
+ + "threw a RemoteException",re);
+ }
+ TestUtility.log(Config.ALL,"Test: " + address + " downloaded "
+ + fileName);
+ if (fileName.equals(randomName) && address.equals(ourAddr)) {
+ fname = fileName;
+ notifyAll();
+ }
+ }
+ }
+
+ private void createTempJar() throws IOException {
+ String iDir = getConfig().getSysConfig().getStringConfigVal(
+ "com.sun.jini.compat.installDir", ".");
+
+ String sep = File.separator;
+ String path = iDir + sep + "lib" + sep + "dl" + sep;
+ String oldJarFileName = path + "compat-lus-dl.jar";
+ tempJarFileName = path + randomName;
+
+ FileInputStream fis = new FileInputStream(oldJarFileName);
+ FileOutputStream fos = new FileOutputStream(tempJarFileName);
+
+ TestUtility.log(Config.ALL,"Test: copying " + oldJarFileName);
+ TestUtility.log(Config.ALL," to " + tempJarFileName);
+
+ //must copy file from one location to the other
+ byte inBytes[] = new byte[1000];
+ int count;
+ while ((count = fis.read(inBytes)) != -1) {
+ fos.write(inBytes, 0, count);
+ }
+ fos.close();
+ fis.close();
+ }
+
+ private void deleteTempJar() {
+ if (tempJarFileName != null) {
+ File f = new File(tempJarFileName);
+ f.delete();
+ TestUtility.log(Config.ALL,"Test: deleted file " + tempJarFileName);
+ }
+ }
+
+ public String[] getCategories() {
+ return (new String[] { BasicClientAdmin.CATEGORY,
+ BasicServiceAdmin.CATEGORY });
+ }
+
+ public Class[] getRequiredAdmins() {
+ return (new Class[] { BasicAdmin.class });
+ }
+
+ public String getDescription() {
+ return "CodeDownloadTest";
+ }
+
+}
+
Propchange: river/tck/src/com/sun/jini/compat/test/CodeDownloadTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: river/tck/src/com/sun/jini/compat/test/EventLeaseExpirationTest.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/test/EventLeaseExpirationTest.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/test/EventLeaseExpirationTest.java (added)
+++ river/tck/src/com/sun/jini/compat/test/EventLeaseExpirationTest.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,211 @@
+/*
+ *
+ * Copyright 2005 Sun Microsystems, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.sun.jini.compat.test;
+
+import com.sun.jini.compat.test.lookup.TestUtils;
+import com.sun.jini.compat.test.lookup.TestImpl;
+import com.sun.jini.compat.test.lookup.TestRegistrar;
+import com.sun.jini.compat.test.lookup.TestException;
+import com.sun.jini.compat.test.lookup.TestFailedException;
+import com.sun.jini.compat.test.lookup.TestUnresolvedException;
+import com.sun.jini.compat.harness.Config;
+
+import net.jini.core.lookup.ServiceRegistrar;
+import net.jini.core.lookup.ServiceEvent;
+import net.jini.core.lookup.ServiceItem;
+import net.jini.core.lookup.ServiceRegistration;
+import net.jini.core.lookup.ServiceTemplate;
+import net.jini.core.event.EventRegistration;
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.event.RemoteEventListener;
+import net.jini.core.lease.UnknownLeaseException;
+import java.rmi.Remote;
+import java.rmi.NoSuchObjectException;
+import java.rmi.RemoteException;
+import java.rmi.StubNotFoundException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Vector;
+
+/** This class is used to test that all event notifications cease to be
+ * delivered after all event leases have expired.
+ *
+ * @see com.sun.jini.compat.test.lookup.Test
+ * @see com.sun.jini.compat.test.lookup.TestImpl
+ * @see com.sun.jini.compat.test.lookup.TestRegistrar
+ * @see com.sun.jini.compat.test.lookup.TestUtils
+ */
+public class EventLeaseExpirationTest extends TestRegistrar {
+
+ /** Class which handles all events sent by the lookup service */
+ public class Listener implements RemoteEventListener {
+ Object proxy;
+ public Listener() throws RemoteException {
+ proxy = UnicastRemoteObject.exportObject((Remote)this);
+ }
+ /** Method called remotely by lookup to handle the generated event. */
+ public void notify(RemoteEvent ev) {
+ ServiceEvent srvcEvnt = (ServiceEvent)ev;
+ evntVec.addElement(srvcEvnt);
+ }
+ public Object getProxy() {
+ return proxy;
+ }
+ }
+
+ /** The event handler for the services registered by this class */
+ private static Listener listener;
+
+ protected Vector evntVec = new Vector();
+
+ private long realLeaseDuration;
+ private ServiceItem[] srvcItems ;
+ private ServiceRegistration[] srvcRegs ;
+ private ServiceTemplate template;
+ private ServiceRegistrar proxy;
+
+ /** Performs actions necessary to prepare for execution of the
+ * current test.
+ *
+ * Creates a single event handler to handle all events generated
+ * by any of the registered service items. Creates the lookup
+ * service. Loads and instantiates all service classes. Registers
+ * each service class instance with the maximum service lease duration.
+ * Retrieves the proxy to the lookup Registrar. Creates a single
+ * ServiceTemplate using ServiceID of registered services.
+ * Register an event notification request based on the contents of that
+ * template, a transition mask including all three transitions, and
+ * a lease duration that is less than the duration of the service
+ * leases.
+ * @exception TestException will usually indicate an "unresolved"
+ * condition because at this point the test has not yet begun.
+ */
+ public void setupQATest() throws TestException {
+ try {
+ listener = new Listener();
+ } catch (RemoteException e) {
+ throw new TestUnresolvedException
+ ("setupQATest: RemoteException from listener creation",e);
+ }
+ super.setupQATest();
+ Config conf = getConfig();
+ srvcItems = super.createServiceItems(TEST_SRVC_CLASSES);
+ srvcRegs = super.registerAll();
+ proxy = super.getProxy();
+ template = new ServiceTemplate(srvcRegs[0].getServiceID(),null,null);
+ try {
+ EventRegistration evntReg = proxy.notify(template,
+ ServiceRegistrar.TRANSITION_NOMATCH_MATCH |
+ ServiceRegistrar.TRANSITION_MATCH_NOMATCH |
+ ServiceRegistrar.TRANSITION_MATCH_MATCH,
+ (RemoteEventListener) listener.getProxy(),
+ null,
+ conf.getFailureTime());
+ long leaseExpiration = evntReg.getLease().getExpiration();
+ long leaseStartTime = TestUtils.getCurTime();
+ realLeaseDuration = leaseExpiration - leaseStartTime;
+ } catch (RemoteException e) {
+ throw new TestUnresolvedException
+ ("setupQATest: RemoteException from notify",e);
+ }
+ }
+
+ /** wait for the event lease to expire and then verify that NO events
+ * have arrived
+ */
+ /** Executes the current test.
+ *
+ * Computes the amount of time to wait to guarantee that all event
+ * leases have expired. Waits that amount of time. Cancels each
+ * service lease (to generate an event for each cancellation). Waits
+ * an appropriate amount of time to allow any events that may be
+ * generated to be sent and collected. Verifies that no events were
+ * sent by the Lookup service.
+ * @exception TestException usually indicates test failure
+ */
+
+ /* The time-line diagram below shows the steps of this test:
+ *
+ * |-----------------------------------------------------------|
+ * : : ^ :
+ * |-------------------| : :
+ * 0 5 secs : :
+ * : : :
+ * : : :
+ * Expires Cancel :
+ * Service :
+ * Lease Analyze
+ */
+ public void doQATest() throws TestException {
+ ServiceEvent evnt = null;
+ /* wait for the event lease to expire */
+ try {
+ Thread.sleep(realLeaseDuration);
+ } catch (InterruptedException e) {
+ }
+
+ /* throw out previous, spurious received events */
+ evntVec = new Vector();
+
+ /* cancel each service lease so as to generate events */
+ for(int i=0; i<srvcRegs.length; i++) {
+ try {
+ srvcRegs[i].getLease().cancel();
+ } catch (UnknownLeaseException e) {
+ throw new TestFailedException
+ ("doQATest: UnknownLeaseException from cancel (index = "
+ +i+")",e);
+ } catch (RemoteException e) {
+ throw new TestFailedException
+ ("doQATest: RemoteException from cancel (index = "
+ +i+")",e);
+ }
+ }
+ /* give the Listener a chance to collect all events */
+ try {
+ Thread.sleep(getConfig().getQuietTime());
+ } catch (InterruptedException e) {
+ }
+
+ /* Verify that no events have arrived. If no events have arrived
+ * the event vector should be empty. If not, declare failure
+ */
+ if (evntVec.size() != 0) {
+ throw new TestFailedException("doQATest: evntVec.size() != 0");
+ }
+ }
+
+ /** Performs cleanup actions necessary to achieve a graceful exit of
+ * the current test.
+ *
+ * Unexports the listener and then performs any remaining standard
+ * cleanup duties.
+ * @exception TestException will usually indicate an "unresolved"
+ * condition because at this point the test has completed.
+ */
+ public void cleanupQATest() throws TestException {
+ try {
+ UnicastRemoteObject.unexportObject((Remote)listener, true);
+ } catch (NoSuchObjectException e) {
+ }
+ super.cleanupQATest();
+ }
+
+ public String getDescription() {
+ return "EventLeaseExpirationTest";
+ }
+}
Propchange: river/tck/src/com/sun/jini/compat/test/EventLeaseExpirationTest.java
------------------------------------------------------------------------------
svn:eol-style = native