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 [14/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/harness/DefaultLookupAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DefaultLookupAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DefaultLookupAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DefaultLookupAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,82 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+import java.rmi.RemoteException;
+import net.jini.core.lookup.ServiceRegistrar;
+import net.jini.core.discovery.LookupLocator;
+
+import com.sun.jini.compat.harness.Config;
+import com.sun.jini.compat.harness.SysConfig;
+
+/**
+ * This is a non-automated generic implementation of the
+ * BasicLookupAdmin. It extends DefaultAdmin for all of it's
+ * BasicAdmin implementation.
+ */
+public class DefaultLookupAdmin extends DefaultAdmin
+   implements BasicLookupAdmin
+{ 
+
+    /**
+     * Basic no-arg constructor.
+     */
+    public DefaultLookupAdmin() {
+    }
+    
+    /**
+     * Returns the ServiceRegistrar from an already started Lookup.
+     * If there are any problems getting the ServiceRegistrar it
+     * throws a RemoteException.  It uses a property called:
+     * <code>com.sun.jini.compat.defaultLookupAdmin.lookupPort</code>.
+     * Using that port and the address of the lookup provided by
+     * the <code>getAddress</code> method it generates a
+     * <code>LookupLocator</code> to get the
+     * <code>ServiceRegistrar</code> for the lookup service being
+     * tested.
+     * 
+     * @return the <code>ServiceRegistrar</code> for the lookup being
+     *         tested.
+     */
+    public ServiceRegistrar getServiceRegistrar()
+	throws RemoteException
+    {
+	Config conf = getConfig();
+	SysConfig sys = conf.getSysConfig();
+	int port =
+	    sys.getIntConfigVal("com.sun.jini.compat.defaultLookupAdmin."+
+				"lookupPort",-1);
+	String lookupURLString = "jini://"+getAddress();
+	if(port != -1)
+	    lookupURLString = lookupURLString+":"+port;
+	lookupURLString = lookupURLString+"/";
+
+	conf.getLog().println("DefaultLookupAdmin attempting to discover "
+            + "lookup service at locator " + lookupURLString);
+	try {
+	    LookupLocator lLoc = new LookupLocator(lookupURLString);
+	    
+	    return lLoc.getRegistrar();
+	} catch( Exception e) {
+	    throw new RemoteException("DefaultLookupAdmin could not get "
+                + "the ServiceRegistrar",e);
+	}
+    }
+}
+	
+

Propchange: river/tck/src/com/sun/jini/compat/harness/DefaultLookupAdmin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/DefaultServiceAdmin.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DefaultServiceAdmin.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DefaultServiceAdmin.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DefaultServiceAdmin.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,124 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.harness;
+
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClassLoader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import net.jini.core.lookup.ServiceItem;
+import net.jini.core.lookup.ServiceTemplate;
+import net.jini.core.lookup.ServiceID;
+
+/**
+ * This is a non-automated generic implementation of the
+ * BasicServiceAdmin.  It extends DefaultAdmin for all it's
+ * BasicAdmin implementation.
+ */
+public class DefaultServiceAdmin extends DefaultAdmin
+   implements BasicServiceAdmin
+{
+    private static String sID = null;
+
+    /**
+     * Basic no-arg constructor.
+     */
+    public DefaultServiceAdmin() {
+    }
+
+    /**
+     * A constructor that takes a message to
+     * be displayed with the various user input requests.
+     *
+     * @param message a message to be displayed with the user input
+     *        requests
+     */
+    public DefaultServiceAdmin(String message) {
+        super(message);
+    }
+
+    /**
+     * Given an array of service proxy objects, this method
+     * asks the user to select the appropriate service from the list.
+     * If the service is not one of the listed services it returns null.
+     *
+     * @param services the array <code>ServiceItem</code> objects
+     *        from which to choose
+     * @return the <code>ServiceItem</code> for the service being tested,
+     * 	      or <code>null</code>
+     */
+    public synchronized ServiceItem pickService(ServiceItem[] services)
+        throws RemoteException
+    {
+        if (sID != null) {
+            for (int i = 0; i < services.length; i++) {
+                Object obj = services[i].service;
+                String tempSID = obj.getClass() +
+                    RMIClassLoader.getClassAnnotation(obj.getClass());
+                if (sID.equals(tempSID)) {
+                    return services[i];
+                }
+            }
+        }
+
+        System.out.println();
+        System.out.println(
+            "Which of the following is the program being tested?");
+        System.out.println("  0) None of these");
+        for (int i = 0; i < services.length; i++) {
+            Object obj = services[i].service;
+            System.out.println("  " + (i+1) + ") " + obj.getClass() 
+                + " from codebase "
+                + RMIClassLoader.getClassAnnotation(obj.getClass()));
+        }
+        System.out.print("Select number and press Enter: ");
+        char sel = waitForChar();
+
+        while (!Character.isDigit(sel)) {
+            System.out.print("You must enter a number. "
+                + "Select number and press Enter: ");
+            sel = waitForChar();
+        }
+        int numSel = Character.getNumericValue(sel);
+        System.out.println();
+        System.out.println("You selected number " + numSel + ".");
+        System.out.println();
+        if (numSel == 0) {
+            return null;
+        }
+
+        Class c = services[numSel - 1].service.getClass();
+        sID = c + RMIClassLoader.getClassAnnotation(c);
+        System.out.println("Storing program proxy class name and codebase "
+            + "for subsequent tests.");
+        return services[numSel - 1];
+    }
+
+    /**
+     * Return a blank <code>ServiceTemplate</code>.
+     *
+     * @return the template
+     */
+    public ServiceTemplate getTemplate() throws RemoteException {
+        return new ServiceTemplate(null, null, null);
+    }
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/DefaultServiceAdmin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/DefaultTest.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DefaultTest.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DefaultTest.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DefaultTest.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,100 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+//java.io
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.PrintWriter;
+import java.io.File;
+
+//java.net
+import java.net.InetAddress;
+
+//java.rmi
+import java.rmi.RemoteException;
+
+/**
+ * This abstract class implements some of the methods of the 
+ * <code>Test</code> interface.  In particular this class implements 
+ * a standard getConfig and setConfig implementation and a standard 
+ * setup method that sets up a scratch directory for use by the test.
+ * In general, LDJ Kit tests extend this class.
+ */
+public abstract class DefaultTest implements Test {
+
+    private Config tConfig = null;
+
+    /** 
+     * Sets up scratch directory for the test.  This is where any
+     * heavy weight operations should go instead of the constructor.
+     */
+    public void setup(String[] args) throws Exception {
+	if(tConfig.getDebugLevel() == tConfig.ALL) {
+            PrintWriter log = tConfig.getLog();
+            if (log == null) {
+                log = new PrintWriter(System.out, true);
+            }
+	    log.print("The setup args are: ");
+	    for(int i = 0; i < args.length; i++) {
+		log.print(args[i]+" ");
+	    }
+	    log.println();
+	}
+
+	SysConfig sysConfig = tConfig.getSysConfig();
+        String dbdir = sysConfig.getStringConfigVal
+            ("com.sun.jini.compat.scratchDir", null);
+
+        // if no scratchDir, use OS-dependent temporary directory
+        if (dbdir == null) {
+            File tmpDir = new File
+                (new String(System.getProperty("java.io.tmpdir")));
+            dbdir = tmpDir.getAbsolutePath();
+        }
+
+	File dir = new File(dbdir);
+	if (!dir.exists()) {
+	    dir.mkdirs();
+	}
+    }
+
+    /**
+     * Tears down any setup that was needed to run the test.
+     */
+    public void tearDown() {
+    }
+
+    /**
+     * Sets the Config object for this test.
+     *
+     * @param tCon the Config object
+     */
+    public void setConfig(Config tCon) {
+	tConfig = tCon;
+    }
+    
+    /**
+     * Gets the Config object for this test.
+     *
+     * @return the Config object
+     */
+    public Config getConfig() {
+	return tConfig;
+    }
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/DefaultTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/DownloadEvent.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DownloadEvent.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DownloadEvent.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DownloadEvent.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,62 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+import java.util.EventObject;
+import java.net.InetAddress;
+
+/**
+ * An event that is sent when the <code>InstrumentedClassServer</code>
+ * has finished downloading a file.
+ */
+public class DownloadEvent extends EventObject {
+
+    private String name;
+    private InetAddress addr;
+    
+    /**
+     * Simple constructor that builds a DownloadEvent.
+     *
+     * @param src The Object which triggered this event
+     * @param nm The name of the file downloaded
+     * @param ia The internet address of the host that downloaded the file
+     */
+    public DownloadEvent(Object src, String nm, InetAddress ia) {
+	super(src);
+	name = new String(nm);
+	addr = ia;
+    }
+    
+    /**
+     * Returns the name of the downloaded file.
+     *
+     * @return the name of the downloaded file
+     */
+    public String getName() {
+	return new String(name);
+    }
+    
+    /**
+     * Returns the address of the host that downloaded the file.
+     *
+     * @return the address of the host
+     */
+    public InetAddress getAddress() {
+	return addr;
+    }
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/DownloadEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/DownloadListener.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/DownloadListener.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/DownloadListener.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/DownloadListener.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,32 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+/**
+ * The listener interface for the <code>DownLoadEvent</code>.  Classes
+ * wishing to be notified when the InstrumentedClassServer is finished
+ * downloading a file should implement this interface.
+ */
+public interface DownloadListener {
+    /**
+     * Callback for classes interested in receiving DownloadEvents.
+     *
+     * @return de the DownloadEvent
+     */
+    public void fileDownloaded(DownloadEvent de);
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/DownloadListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/InstrumentedClassServer.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/InstrumentedClassServer.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/InstrumentedClassServer.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/InstrumentedClassServer.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,110 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+// java.util
+import java.util.Iterator;
+import java.util.ArrayList;
+
+// java.io
+import java.io.IOException;
+
+// java.net
+import java.net.URL;
+import java.net.InetAddress;
+
+// com.sun.jini
+import com.sun.jini.compat.tool.ClassServer;
+
+/**
+ * A subclass of <cod>ClassServer</code> which is a simple
+ * http server for class files.  This class adds the ability to
+ * register listeners that get notified when a file is finished
+ * downloading and a method to get the base url for this server (this
+ * is especially useful for building codebases).
+ */
+public class InstrumentedClassServer extends ClassServer {
+
+    private ArrayList listeners;
+    private URL serverURL;
+
+    /**
+     * A constructor that takes the same arguments as the ClassServer.
+     * 
+     * @see com.sun.jini.compat.tool.ClassServer
+     */
+    public InstrumentedClassServer(int port, String dir,
+				   boolean trees, boolean verbose)
+	throws IOException
+    {
+	super(port, dir, trees, verbose);
+	serverURL = new URL("http://" + 
+			    InetAddress.getLocalHost().getHostAddress() + 
+			    ":" + port + "/");
+	listeners = new ArrayList();
+    }
+
+    /**
+     * Provides the root URL for this http server.
+     *
+     * @return a URL that points to the root of this http server.
+     */
+    public URL getCodeURL() {
+	return serverURL;
+    }
+
+    /**
+     * Overrides a method in ClassServer that gets called whenever
+     * a file is finished downloading.  This method notifies all the
+     * listeners.
+     */
+    protected void fileDownloaded(String fp, InetAddress addr) {
+	synchronized(listeners) {
+	    Iterator i = listeners.iterator();
+	    while (i.hasNext()) {
+		DownloadListener dl = (DownloadListener)i.next();
+		DownloadEvent de = new DownloadEvent(this, fp, addr);
+		dl.fileDownloaded(de);
+	    }
+	}
+    }
+
+    /**
+     * Adds listeners for file downloads.
+     *
+     * @param dl the DownLoadlistener to add
+     */
+    public void addDownloadListener(DownloadListener dl) {
+	synchronized(listeners) {
+	    listeners.add(dl);
+	}
+    }
+    
+    /**
+     * Removes listeners for file downloads.  Uses Object.equals.
+     *
+     * @param dl the DownloadListener to remove
+     */
+    public void removeDownloadListener(DownloadListener dl) {
+	synchronized(listeners) {
+	    if (listeners.contains(dl)) {
+	        listeners.remove(listeners.indexOf(dl));
+	    }
+	}
+    }
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/InstrumentedClassServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/MulticastPacketGatherer.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/MulticastPacketGatherer.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/MulticastPacketGatherer.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/MulticastPacketGatherer.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,176 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+import net.jini.discovery.Constants;
+import net.jini.core.lookup.ServiceID;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+import java.net.DatagramPacket;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+/**
+ * A thread that gathers multicast packets asynchronously and notifies
+ * waiting threads when new packets arrive.
+ */
+public class MulticastPacketGatherer extends Thread {
+
+    private List packets;
+    private boolean ready = false;
+    private boolean interrupted = false;
+    private MulticastSocket ms;
+    private BasicAdmin admin;
+
+    /**
+     * Constructor that takes the admin of the program being tested.
+     *
+     * @param admin the admin of the program being tested
+     */
+    public MulticastPacketGatherer(BasicAdmin admin) {
+	packets = new ArrayList();
+	this.admin = admin;
+    }
+
+    /**
+     * Indicates whether the packet gatherer is ready to receive packets
+     * 
+     * @return <code>true</code> if the gatherer is ready
+     */
+    public synchronized boolean isReady() {
+	return ready;
+    }
+
+    /**
+     * Returns all of the packets that have been gathered since 
+     * the last call to this method.  It removes all the previous
+     * packets from the gatherer's list.
+     *
+     * @return List of the gathered DatagramPackets, may be empty
+     */
+    public synchronized List getPackets() {
+	List p = packets;
+	packets = new ArrayList();
+	return p;
+    }
+
+    /**
+     * Overrides Thread.interrupt().  This is a workaround for
+     * Thread.interrupt not working on
+     * MulticastSocket.receive on all platforms.
+     */
+    public void interrupt() {
+        interrupted = true;
+        ms.close();
+    }
+
+    /**
+     * Overrides Thread.isInterrupted().
+     */
+    public boolean isInterrupted() {
+        return interrupted;
+    }
+
+    /**
+     * Determines if the parameter represents a correctly
+     * formated multicast announcement.
+     */
+    private boolean isAnnouncement(DatagramPacket p) {
+	try {
+            ByteArrayInputStream bs = new ByteArrayInputStream(p.getData());
+            DataInputStream ds = new DataInputStream(bs);
+            int protoVersion = ds.readInt();
+            if (protoVersion != 1)
+		return false;
+            String host = ds.readUTF();
+            int port = ds.readInt();
+            if (port <= 0 || port >= 65536)
+		return false;
+	    ServiceID serviceID = new ServiceID(ds);
+            int groupCount = ds.readInt();
+            // We know that the minimal length of a string written with
+            // DataOutput.writeUTF is two bytes (for the empty string), so
+            // we make some attempt to see if the count can plausibly fit
+            // into this packet.
+            if (groupCount < 0 || groupCount > bs.available() / 2)
+		return false;
+            for (int i = 0; i < groupCount; i++)
+                ds.readUTF();
+	} catch (Exception e) {
+	    return false;
+	}
+	return true;
+    }
+
+    /**
+     * Standard thread run method.  This method notifies waiting
+     * threads that the gatherer is ready for packets and then
+     * receives the packets continuously in a loop.  Packets
+     * that represent valid announcements are ignored (BugID#: 4466755).
+     */
+    public void run() {
+	try {
+	    ms = new MulticastSocket(Constants.discoveryPort);
+	    ms.joinGroup(Constants.getRequestAddress());
+	    
+	    // tell others we are ready to receive
+	    synchronized(this) {
+		ready = true;
+		notifyAll();
+	    }
+
+	    while (!isInterrupted()) {
+		byte[] buf = new byte[513];
+		DatagramPacket pkt = new DatagramPacket(buf, buf.length);
+		try {
+		    ms.receive(pkt);
+		    if (pkt.getAddress().equals(admin.getAddress())) {
+			if (isAnnouncement(pkt)) {
+			    TestUtility.log(Config.ALL,"PacketGatherer: "
+			    + "ignoring multicast announcement packet from " 
+			    + pkt.getAddress());
+			} else {
+			    synchronized(this) {
+			        packets.add(pkt);
+			        notifyAll();
+			    }
+			}
+		    } else {
+			TestUtility.log(Config.ALL,"PacketGatherer: ignoring "
+			    + "packet from " + pkt.getAddress());
+		    }
+                } catch (InterruptedIOException ignore) {}
+	    }
+	} catch(Exception ignore) {}
+
+	try {
+	    if (ms != null) {
+		ms.leaveGroup(Constants.getRequestAddress());
+		ms.close();
+	    }
+	} catch(IOException ignore) {}
+    }
+    
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/MulticastPacketGatherer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/RegistrationListener.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/RegistrationListener.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/RegistrationListener.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/RegistrationListener.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,138 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.RemoteException;
+
+import net.jini.core.event.RemoteEventListener;
+import net.jini.core.event.RemoteEvent;
+import net.jini.core.lookup.ServiceEvent;
+import net.jini.core.lookup.ServiceItem;
+
+/**
+ * This class implements the RemoteEventListener interface (by way of
+ * the RegistrationListener interface).  It takes remote ServiceEvents
+ * and notifies a lock object when the event is related to the
+ * service being tested.  It also sets a flag when this happens so
+ * that the lock object knows whether it has timed out or actually
+ * been notified.
+ */
+public class RegistrationListener extends UnicastRemoteObject
+    implements RemoteEventListener 
+{
+    /** 
+     * The object to notify when something happens to the service 
+     * being tested 
+     */
+    private Object lock = null;
+    
+    /** 
+     * The admin for the service so that we can determine if the
+     * ServiceEvent is for the right service
+     */
+    private BasicServiceAdmin admin = null;
+    
+    /**
+     * The flag denoting whether this listener has actually been
+     * notified for the service being tested
+     */
+    private boolean notified = false;
+
+    /**
+     * If we do get notified about the right service here is the
+     * service item for it
+     */
+    private ServiceItem serviceItem = null;
+
+    /**
+     * Constructor that takes the lock object and the admin for the service.
+     * 
+     * @param lock the object to notify
+     * @param admin the admin for the service being tested
+     */
+    public RegistrationListener(Object lock, BasicServiceAdmin admin)
+	throws RemoteException
+    {
+	this.lock = lock;
+	this.admin = admin;
+    }
+    
+    /**
+     * Returns <code>true</code> if this remote event listener
+     * has received an event related to the service being tested.
+     *
+     * @return <code>true</code> if this listener was notified of an event
+     */
+    public synchronized boolean getNotified() {
+	return notified;
+    }
+
+    /**
+     * If we get notified about the service being tested, this method
+     * returns the <code>ServiceItem</code> from the event.  Otherwise,
+     * <code>null</code> is returned.
+     *
+     * @return the <code>ServiceItem</code> from the notification event,
+     *         or <code>null</code> if no event received or a MATCH_NOMATCH
+     *         transition occured in which case the event does not contain
+     *         the <code>ServiceItem</code>
+     */
+    public synchronized ServiceItem getServiceItem() {
+	return serviceItem;
+    }
+
+    /**
+     * Gets a notification from a lookup service and uses the 
+     * service admin pickService method to determine if the event is 
+     * related to the service being tested. If it is, this method 
+     * notifies the lock object and sets the notified flag to 
+     * <code>true</code>.  If the serviceItem field of the remote
+     * event is null, the event ignored and the state of the listener
+     * is unchanged.
+     *
+     * @param theEvent the remote event received from a lookup service
+     */
+    public void notify(RemoteEvent theEvent) {
+	if (!notified) {
+	    ServiceEvent se = (ServiceEvent) theEvent;
+	    ServiceItem si = se.getServiceItem();
+	    
+	    if ((si != null) && (si.service != null)) {
+	        try {
+		    si = admin.pickService(new ServiceItem[] {si});
+	        } catch (RemoteException re) {
+		    System.err.println("Couldn't pick service");
+		    re.printStackTrace();
+	        }
+	    
+	        if (si != null) { 
+		    synchronized(this) {
+			notified = true;
+			serviceItem = si;
+		    }
+		    synchronized(lock) {
+		        lock.notify();
+		    }
+	        }
+	    }
+	}
+    }
+
+}
+

Propchange: river/tck/src/com/sun/jini/compat/harness/RegistrationListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/Runner.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/Runner.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/Runner.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/Runner.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,291 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+// java.io
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.FileNotFoundException;
+
+// java.util
+import java.util.Properties;
+import java.util.Date;
+
+/**
+ * This class acts as a batch runner for all of the tests in the 
+ * Jini(TM) Technology Lookup, Discovery, and Join Compatibility Kit (LDJ Kit).
+ * Based on the category of the program being tested
+ * (either client, service or lookup) it determines the set of tests
+ * that should be run.  This can be overridden with tests specified
+ * on the command-line.
+ *
+ * @see com.sun.jini.compat.harness.Test
+ */
+public class Runner extends AbstractRunner {
+
+    /**
+     * Standard constructor for the Runner.  This constructor
+     * takes the command-line arguments and a PrintWriter for 
+     * logging test output.
+     *
+     * @param args      <code>String</code> array containing the command line
+     *                  arguments
+     * @param log       an instance of <code>java.io.PrintWriter</code>
+     *                  through which all test output is written
+     */
+    public Runner(String[] args, PrintWriter log) {
+        super(args,log);
+    }
+
+    /**
+     * Retrieves the information contained in 
+     * the top-level configuration property file identified by the 
+     * <code>configFile</code> parameter.  The information is stored 
+     * in the return value for access throughout the test run.
+     *
+     * @param configFile the name of the property file containing the
+     *                   top-level configuration information for all
+     *                   tests to be executed on the current run
+     * @param log        an instance of <code>java.io.PrintWriter</code>
+     *                   through which all test output is written
+     *
+     * @return the Config object that stores the retrieved information
+     */
+    protected Config doConfig(String configFile, PrintWriter log) {
+        InstrumentedClassServer ics = null;
+        try {
+            ics = startClassServer(configFile);
+        } catch(Exception e) {
+            log.println("Problem starting ClassServer:");
+	    e.printStackTrace(log);
+    	    System.exit(1);
+        }
+
+        Config tConfig = null;
+        try {
+            tConfig = new Config(configFile, ics, log);
+	    TestUtility.setLog(tConfig);
+        } catch(FileNotFoundException fnf) {
+            log.println("Cannot find file: " + configFile);
+            usage();
+            System.exit(1);
+        } catch(Exception e) {
+            log.println("Problem setting up Configuration:");
+	    e.printStackTrace(log);
+            System.exit(1);
+        }
+
+        return tConfig;
+    }
+
+    /**
+     * Adds all possible tests for the current test run.
+     */
+    protected void addAllTests() {
+	// client and service tests
+	addTest("com.sun.jini.compat.test.RequestPacketTest");
+	addTest("com.sun.jini.compat.test.UnicastRequestTest");
+	addTest("com.sun.jini.compat.test.CodeDownloadTest");
+	// service tests
+	addTest("com.sun.jini.compat.test.AnnouncementResponseTest");
+	addTest("com.sun.jini.compat.test.RegistrationTest");
+	addTest("com.sun.jini.compat.test.MultipleRegistrationTest");
+	addTest("com.sun.jini.compat.test.PublicGroupTest");
+	addTest("com.sun.jini.compat.test.NonPublicGroupTest");
+	addTest("com.sun.jini.compat.test.MultipleGroupTest");
+	addTest("com.sun.jini.compat.test.LeaseTest");
+	// lookup tests
+	addTest("com.sun.jini.compat.test.LookupByServiceIDTest");
+	addTest("com.sun.jini.compat.test.LookupByClassTest");
+	addTest("com.sun.jini.compat.test.LookupBySuperClassTest");
+	addTest("com.sun.jini.compat.test.LookupByInterfaceTest");
+	addTest("com.sun.jini.compat.test.MultipleServiceLeaseRenewalTest");
+	addTest("com.sun.jini.compat.test.ServiceLeaseExpirationTest");
+	addTest("com.sun.jini.compat.test.ServiceIDTest");
+	addTest("com.sun.jini.compat.test.MultipleEventLeaseRenewalTest");
+	addTest("com.sun.jini.compat.test.EventLeaseExpirationTest");
+    }
+
+    /**
+     * Prints the harness usage message to standard output.
+     */
+    protected void usage() {
+        System.out.print("Usage: Runner configFilename ");
+        System.out.print("[-categor[y|ies] cat1,cat2]");
+        System.out.println("[-tests test1,test2] [-noduplicates] [-gui]");
+        System.out.print("[-xcategories] cat1,cat2]");
+        System.out.println("[-xtests test1,test2]");
+        System.out.println("Descriptions:");
+        System.out.println("configFilename");
+        System.out.println("\tThe name of the properties file");
+        System.out.println("\tfor this run of tests");
+        System.out.println("-categor[y|ies]");
+        System.out.println("\tA comma separated list ");
+        System.out.println("\tof the categories this program is being ");
+        System.out.println("\ttested in.  If it is not specified here ");
+        System.out.println("\tit must be specified in the properties ");
+        System.out.println("\tfile as com.sun.jini.compat.categories");
+        System.out.println("-tests");
+        System.out.println("\tA comma separated list of tests ");
+        System.out.println("\tthat you wish to run.  These tests are");
+        System.out.println("\tonly run if they are appropriate for ");
+        System.out.println("\tthe categories the program is in");
+        System.out.println("-noduplicates");
+        System.out.println("\tDoes not allow tests to be run more");
+        System.out.println("\tthan once even if they are specified");
+        System.out.println("\tmultiple times");
+        System.out.println("-gui");
+        System.out.println("\tCurrently not supported.  ");
+        System.out.println("\tEventually this will run a GUI to ");
+        System.out.println("\tconfigure and run the tests.");
+        System.out.println("-xcategories (optional)");
+        System.out.println("\tA comma separated list of the categories");
+        System.out.println("\tto exclude from the current test run. Any");
+        System.out.println("\ttest belonging to one or more of these");
+        System.out.println("\tcategories will not be run.");
+        System.out.println("-xtests (optional)");
+        System.out.println("\tA comma separated list of the tests");
+        System.out.println("\tto exclude from the current test run");
+    }
+
+    private InstrumentedClassServer startClassServer(String configFile) 
+	throws Exception
+    {
+	SysConfig sys = new SysConfig(configFile);
+	
+	String classDir =
+	    sys.getStringConfigVal("com.sun.jini.compat.installDir", ".");
+	
+	InstrumentedClassServer ics = new
+	    InstrumentedClassServer(8080, classDir+"/lib/dl", false, false);
+				    
+	ics.start();
+	
+	return ics;
+    }
+	
+    /**
+     * This is the starter method for the LDJ Kit.
+     *
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+	PrintWriter log = new PrintWriter(System.out, true);
+	Runner runner = new Runner(args, log);
+
+        SysConfig sysConfig = runner.getConfig().getSysConfig();
+
+	long startTime = System.currentTimeMillis();
+        String installDir = "com.sun.jini.compat.installDir";
+        String scratchDir = "com.sun.jini.compat.scratchDir";
+        String platformDir = "com.sun.jini.compat.lookupPlatformDir";
+        String failureTime = "com.sun.jini.compat.failureTime";
+        String quietTime = "com.sun.jini.compat.unofficialQuietTime";
+        String categories = "com.sun.jini.compat.categories";
+        String debugLevel = "com.sun.jini.compat.debugLevel";
+        String adminClass = "com.sun.jini.compat.adminClass";
+	String address = null;
+        try {
+            address = runner.getConfig().getAdmin().getAddress().toString();
+        } catch (Exception e) {
+            address = "ERROR: " + e;
+        }
+
+        log.println();
+        log.println("---------------------------");
+        log.println("LDJ KIT PROPERTIES:");
+        log.println();
+	log.println("   Date started:");
+	log.println("      " + (new Date(startTime)).toString());
+        log.println("   Installation directory of the LDJ Kit:");
+        log.println("      " + installDir + "="
+                           + sysConfig.getStringConfigVal(installDir,""));
+        log.println("   Scratch directory for the LDJ Kit:");
+        log.println("      " + scratchDir + "="
+                           + sysConfig.getStringConfigVal(scratchDir,""));
+        log.println("   Platform directory for the LDJ Kit Lookup Service:");
+        log.println("      " + platformDir + "="
+                           + sysConfig.getStringConfigVal(platformDir,null));
+        log.println("   Failure time (in milliseconds):");
+        log.println("      " + failureTime + "="
+                           + runner.getConfig().getFailureTime());
+        log.println("   Quiet time (in milliseconds):");
+        log.println("      " + quietTime + "="
+                           + runner.getConfig().getQuietTime());
+        log.println("   Categories being tested:");
+        log.println("      " + categories + "="
+                           + sysConfig.getStringConfigVal(categories,""));
+        log.println("   Debug output level of the LDJ Kit:");
+        log.println("      " + debugLevel + "="
+                           + sysConfig.getStringConfigVal(debugLevel,""));
+        log.println("   Admin class for the program-under-test:");
+        log.println("      " + adminClass + "="
+                           + sysConfig.getStringConfigVal(adminClass,""));
+        log.println("   IP address of the program-under-test:");
+        log.println("      " + adminClass + ".getAddress()=" + address);
+
+	Properties properties = System.getProperties();
+        log.println();
+        log.println("---------------------------");
+        log.println("ENVIRONMENT PROPERTIES:");
+	log.println(); 
+	log.println("   JVM information:");
+	log.println("      " + properties.getProperty("java.vm.name","unknown")
+			   + ", " + properties.getProperty("java.vm.version"));
+	log.println("      " + properties.getProperty("java.vm.vendor",""));
+	log.println("   LDJ Kit VM classpath:");
+        log.println("      " + properties.getProperty(
+			                       "java.class.path","unknown"));
+	log.println("   OS information:");
+	log.println("      " + properties.getProperty("os.name","unknown")
+			   + ", " + properties.getProperty("os.version")
+			   + ", " + properties.getProperty("os.arch"));
+        log.println();
+
+        scratchDir = sysConfig.getStringConfigVal
+            ("com.sun.jini.compat.scratchDir", null);
+        if (scratchDir != null) {
+            File dir = new File(scratchDir);
+            if (!dir.exists()) {
+                if (!dir.mkdirs()) {
+                    log.println("Environment Failure: unable "
+			+ "to create the directory specified by the "
+			+ "com.sun.jini.compat.scratchDir property; "
+			+ "see property file comments");
+		    System.exit(1);
+		}
+            } else if (!dir.isDirectory()) {
+                log.println("Environment Failure: the directory "
+                    + "specified by the com.sun.jini.compat.scratchDir property "
+                    + "appears to be an existing file");
+		System.exit(1);
+	    }
+        }
+
+	boolean result = runner.runTests();  // run LDJ Kit tests
+
+	log.println();
+	log.println("   Date finished:");
+	log.println("      " + (new Date()).toString());
+	log.println("   Time elapsed:");
+	log.println("      " + 
+	    ((System.currentTimeMillis() - startTime)/1000) + " seconds");
+	log.println();
+	System.exit( ( result ? 0 : 1 ) );
+    }
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/Runner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/Status.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/Status.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/Status.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/Status.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,128 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+import java.io.PrintWriter;
+
+/**
+ * This class is a simple holder class that holds the status of a
+ * test.  The Status for a test consists of whether the test passed or
+ * failed, a short message, and if the test failed the reason for the
+ * failure.
+ */
+public class Status {
+    
+    /**
+     * Failure type. Indicates that a test failed because the program failed.
+     */
+    public final static int TEST = 0;
+    
+    /**
+     * Failure type. Indicates that a test failed because of something wrong
+     * with the environment, not with the program.
+     */
+    public final static int ENV = 1;
+    
+    /**
+     * Failure type. Indicates that a test failed but the reason for 
+     * failure may be external to the program being tested.
+     */
+    public final static int INDEF = 2;
+    
+    private String message = null;
+    private boolean state = false;
+    private int type = TEST;
+    
+    /**
+     * The standard constructor.  This constructor takes all the
+     * arguments to fully specify the status.  It is seldom used.
+     * Instead the static methods: <code>passed()</code> and
+     * <code>failed()</code> are used to construct new
+     * <code>Status</code> objects.
+     *
+     * @param message  a message that will be printed with the status
+     * @param passed   the state of the status: failed=false, passed=true
+     * @param failtype the failure type
+     */
+    public Status(String message, boolean passed, int failtype) {
+	this.message = new String(message);
+	this.state = passed;
+	this.type = failtype;
+    }
+
+    /**
+     * A static method that is used to construct passed <code>Status</code>
+     * objects with a message.
+     * 
+     * @param message the message to be printed with the status
+     *
+     * @return the new <code>Status</code> object
+     */
+    public static Status passed(String message) {
+	return new Status(message, true, TEST);
+    }
+
+    /**
+     * A static method that is used to construct failed <code>Status</code>
+     * objects with a message and a type.  The failure type specifies if 
+     * the failure was environment related or program non-function related.
+     *
+     * @param type    the failure type
+     * @param message the message to be printed with the status
+     *
+     * @return the new <code>Status</code> object
+     */
+    public static Status failed(int type, String message) {
+	return new Status(message, false, type);
+    }
+    
+    /**
+     * Prints the status object out to the PrintWriter provided.
+     *
+     * @param log the PrintWriter to print the status to
+     */
+    public void displayResults(PrintWriter log) {
+	String outMess = "Test ";
+	if(state)
+	    outMess += "Passed: ";
+	else {
+	    outMess += "Failed (";
+	    if(type == ENV)
+		outMess += "Environment Problem): ";
+	    else if(type==INDEF)
+		outMess += "Indefinite Cause):";
+	    else
+		outMess += "Service Failed): ";
+	}
+	
+	outMess += message;
+
+	log.println(outMess);
+    }
+
+    /**
+     * Returns a <code>boolean</code> that represents the the state of
+     * this object. 
+     *
+     * @return <code>true</code> if the state is "passed"; <code>false</code>
+     *         if the state is "failed". 
+     */
+    public boolean getState() {
+        return state;
+    }	
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/Status.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: river/tck/src/com/sun/jini/compat/harness/SysConfig.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/SysConfig.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/SysConfig.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/SysConfig.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,522 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+// java.util
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+// java.io
+import java.io.FileInputStream;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileOutputStream;
+
+/** 
+ *  A class used to simplify the access to properties in property files.
+ */
+public class SysConfig {
+
+    private ConfigProperties configProps = null;
+
+    /**
+     * This constructor will attempt to open the properties file corresponding
+     * to the path and filename supplied in configFilename.
+     * If the file does not exist, or for any reason the file can not be
+     * opened, the constructor will return without instantiating the 
+     * properties list. Note that the methods of this class which retrieve
+     * values from the properties list will test for the existence of the list 
+     * prior to attempting to retrieve a property value. Those methods will
+     * return the default value if the list or the property value itself
+     * does not exist. In this way, a process can use this class with or
+     * without a configuration file; the absence of a configuration file
+     * will result in the process using its default values.
+     *
+     * @param configFilename the property file name
+     */
+    public SysConfig(String configFilename) throws IOException {
+        if (configFilename != null) {
+            FileInputStream fis = new FileInputStream(configFilename);
+            BufferedInputStream bis = new BufferedInputStream(fis);
+            configProps = new ConfigProperties();
+            configProps.load(bis);
+            bis.close(); // must close since load() does not close the stream
+        }
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'int'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public int getIntConfigVal(String propertyName, int defaultVal) {
+        int val = defaultVal;
+        String strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            if (strVal != null) {
+	        try {
+                    val = Integer.parseInt(strVal);
+	        } catch (NumberFormatException ignore) { }
+	    }
+	}
+        return val;
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'long'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public long getLongConfigVal(String propertyName, long defaultVal) {
+        long val = defaultVal;
+        String strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            if (strVal != null) {
+	        try {
+                    val = Long.parseLong(strVal);
+	        } catch (NumberFormatException ignore) { }
+	    }
+	}
+        return val;
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'float'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public float getFloatConfigVal(String propertyName, float defaultVal) {
+        float val = defaultVal;
+        String strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            if (strVal != null) {
+	        try {
+                    float tmpval = (Float.valueOf(strVal)).floatValue();
+                    if (!(Float.isInfinite(tmpval))&&!(Float.isNaN(tmpval)) ) {
+                       val = tmpval;
+		    }
+	        } catch (NumberFormatException ignore) { }
+	    }
+	}
+        return val;
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'double'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public double getDoubleConfigVal(String propertyName, double  defaultVal) {
+        double val = defaultVal;
+        String strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            if (strVal != null) {
+	        try {
+                    double tmpval = (Double.valueOf(strVal)).doubleValue();
+                    if (!(Double.isInfinite(tmpval))&&!(Double.isNaN(tmpval))){
+                        val = tmpval;
+	  	    }
+	        } catch (NumberFormatException ignore) { }
+	    }
+	}
+        return val;
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'String'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public String getStringConfigVal(String propertyName,
+                                     String defaultVal) {
+        String strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            return (strVal != null ? strVal : defaultVal);
+	} else {
+            return defaultVal;
+	}
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the value of a property whose name corresponds to the string
+     * contained in the input argument "propertyName" and whose value
+     * is of type 'boolean'.
+     * <p>
+     * If the property list does not exist, or if the string value of the
+     * property can not be "cast" to the expected data type, then the
+     * default value will be returned.
+     */
+    public boolean getBooleanConfigVal(String propertyName,boolean defaultVal) {
+        boolean val    = defaultVal;
+        String  strVal = null;
+        if (configProps != null) {
+            strVal = configProps.getProperty(propertyName);
+            if (strVal != null) {
+                val = (Boolean.valueOf(strVal)).booleanValue();
+	    }
+	}
+        return val;
+    }
+
+    /**
+     * This method will retrieve from the locally stored property list,
+     * the String value of a "propertyName".  The value is assumed 
+     * to be a path and (possibly) a filename.
+     * <p>
+     * If the property list does not exist then the
+     * default value will be returned.
+     * <p>
+     * The goal of this method is to take the path/filename String represented
+     * in the property corresponding to the given propertyName and "compute"
+     * a well-formed absolute path/filename. This method is intended to be
+     * sensitive to file system dependencies. For example, if the property is
+     * written in DOS file format (ex. C:\aaa\bbb\ccc\), but this method
+     * is executed on a system with a unix file system, this method will
+     * build a String in the unix file system format from the contents of the
+     * given String (/aaa/bbb/ccc).
+     * <p>
+     * In addition to being sensitive to file system differences, this method
+     * is also designed to handle both absolute and relative paths in a 
+     * well-defined manner.
+     *
+     * @param propertyName <code>String</code> containing the name of the 
+     *                     property whose value should be retrieved and
+     *                     converted to the appropriate format
+     * @param defaultVal   the <code>String</code> value to use if the 
+     *                     property given in the propertyName parameter does
+     *                     not exist, or cannot be retrieved. 
+     *
+     * @return a <code>String</code> containing a path/filename constructed
+     *         from the value of the propertyName parameter and the 
+     *         "com.sun.jini.compat.installDir" property in a format that is
+     *         appropriate to the current file system.
+     */
+    public String getPathConfigVal(String propertyName, String defaultVal) {
+        String path = getStringConfigVal(propertyName, defaultVal);
+        if(path == null) {
+	    return path;
+	}
+
+        String installDir = getStringConfigVal
+                              ("com.sun.jini.compat.installDir",new String(""));
+
+        return relativeToAbsolutePath(installDir,path);
+    }
+
+    /**
+     * This method constructs a well-formed, absolute path/filename from the
+     * given <code>path</code> parameter. If the <code>path</code> parameter
+     * is not already absolute, the OS-dependent absolute path constructed
+     * from the current directory is pre-pended to the <code>path</code>
+     * parameter, and the adjustments are made to the format of the output
+     * for the current file system.
+     *
+     * @param path       <code>String</code> containing the name of the
+     *                   path/filename to process
+     *
+     * @return a <code>String</code> containing a path/filename constructed
+     *         from the value of the input parameter in a format that is
+     *         appropriate to the current file system.
+     */
+    public String relativeToAbsolutePath(String path) {
+        return relativeToAbsolutePath(null,path);
+    }//end getPathConfigVal
+
+    /**
+     * This method constructs a well-formed, absolute path/filename from the
+     * given <code>installDir</code> and <code>path</code> parameters. This
+     * method is intended to be sensitive to file system dependencies.
+     * For example, if the property is written in DOS file format
+     * (ex. C:\aaa\bbb\ccc\), but this method is executed on a system with
+     * a unix file system, this method will build a String in the unix file
+     * system format from the contents of the given String (/aaa/bbb/ccc).
+     * <p>
+     * In addition to being sensitive to file system differences, this method
+     * is also designed to handle both absolute and relative paths in a 
+     * well-defined manner. If the path/filename corresponding to the given
+     * <code>path</code> parameter is absolute, that path/filename will be
+     * converted to the appropriate file system format with no other
+     * modifications or additions applied. On the other hand, if the
+     * <code>path</code> parameter is relative, then the value contained in
+     * <code>installDir</code> parameter will be prepended to the 
+     * <code>path</code> parameter, and the result will be returned in the
+     * appropriate file system format.
+     * <p>
+     * Whether a given path/filename is viewed as relative or absolute is
+     * based on the following criteria:
+     * <p><pre>
+     *  non-DOS file systems  abs/rel    DOS file systems  abs/rel
+     *  --------------------  --------   ----------------  --------
+     *     /aaa/bbb/ccc       absolute    c:\aaa\bbb\ccc   absolute
+     *     aaa/bbb/ccc        relative      \aaa\bbb\ccc   relative
+     *                                      \\aaa\bbb\ccc  relative
+     *                                        aaa\bbb\ccc  relative
+     * </pre><p> 
+     * Note that this method also attempts to handle the case where the 
+     * format of the given <code>path</code> parameter is different than
+     * the current file system's format. For example,
+     * <p><pre>
+     * file sys installDir      path      abs/rel         output 
+     * -------- ---------- -------------- --------  --------------------
+     *   DOS     c:\files  c:\aaa\bbb\ccc absolute  c:\aaa\bbb\ccc
+     *   unix    c:\files  c:\aaa\bbb\ccc absolute    /aaa/bbb/ccc
+     *   DOS     c:\files     aaa\bbb\ccc relative  c:\files\aaa\bbb\ccc
+     *   unix    c:\files     aaa\bbb\ccc relative    /files/aaa/bbb/ccc
+     * </pre>
+     * @param installDir <code>String</code> containing the name of the
+     *                   directory to prepend to the <code>path</code>
+     *                   parameter; if not an absolute path, it will be
+     *                   made one using File.getAbsolutePath()
+     * @param path       <code>String</code> containing the name of the
+     *                   path/filename to modify (if necessary);  if not
+     *                   an absolute path, it will be made one by prepending
+     *                   the absolute path of <code>installDir</code>
+     *
+     * @return a <code>String</code> containing an absolute path/filename 
+     *         constructed from the value of the input parameters in a 
+     *         format that is appropriate to the current file system.
+     */
+    public String relativeToAbsolutePath(String installDir, String path) {
+        if (path == null) {
+            return path;
+        }
+
+        if (isAbsolute(path)) { // absolute path, don't prepend installDir
+            // re-build the path with "clean" components
+            StringBuffer pBuf = new StringBuffer();
+            String pDir = getAbsolutePath(path);
+            String pDirComponents[] = getDirs(pDir);
+            int pStart = 0;
+            if (hasDrive(pDir)) {
+                pBuf.append(pDirComponents[0]);
+                pStart = 1;
+            }
+            for (int i = pStart; i < pDirComponents.length; i++) {
+                pBuf.append(File.separator + pDirComponents[i]);
+            }
+            return pBuf.toString();
+        } else { // relative path, prepend installDir
+            String iDir = null;
+            if (installDir != null) {
+                // re-build the install directory with "clean" components
+                StringBuffer iBuf = new StringBuffer();
+                iDir = getAbsolutePath(installDir);
+                String iDirComponents[] = getDirs(iDir);
+                int iStart = 0;
+                if (hasDrive(iDir)) {
+                    iBuf.append(iDirComponents[0]);
+                    iStart = 1;
+                } else if (dosFileSystem()) { // no drive but windows: get drive
+                    iBuf.append(getFileSystemDrive() + getDriveSeparator());
+                }
+                for (int i = iStart; i < iDirComponents.length; i++) {
+                    iBuf.append(File.separator + iDirComponents[i]);
+                }
+                iDir = iBuf.toString();
+            }
+
+            // construct the new path by pre-pending the installDir
+            String pDir = path;
+            String pDirComponents[] = getDirs(pDir);
+            int pStart = 0;
+            StringBuffer pBuf = new StringBuffer();
+            // if no install directory, use OS-dependent absolute path
+            if ((iDir == null) || (iDir.length() == 0)) { // no installDir
+                pDir = getAbsolutePath(path);
+                pDirComponents = getDirs(pDir);
+                if (hasDrive(pDir)) {
+                    pBuf.append(pDirComponents[0]);
+                    pStart = 1;
+                } else if (dosFileSystem()) {
+                    pBuf.append(getFileSystemDrive() + getDriveSeparator());
+                }
+            } else { // prepend the install directory
+                pBuf.append(iDir);
+            }
+
+            // re-build path with install directory and "clean" components
+            for (int i = pStart; i < pDirComponents.length; i++) {
+                pBuf.append(File.separator + pDirComponents[i]);
+            }
+            return pBuf.toString();
+        }
+    }//end relativeToAbsolutePath
+
+    /** Returns the value associated with the "com.sun.jini.filesystem.drive"
+     *  property, or a default drive of "c".
+     *
+     *  @return <code>String</code> containing the drive letter contained
+     *          in the "com.sun.jini.filesystem.drive" property.
+     */
+    private String getFileSystemDrive() {
+        return (dosFileSystem() ? 
+                    getStringConfigVal("com.sun.jini.filesystem.drive","c")
+                    : "");
+    }
+
+    /** Returns the drive separator associated with the current file system.
+     *  For example, on DOS files systems, ":" would be returned, whereas on
+     *  unix file systems, "" would be returned.
+     *
+     * @return <code>String</code> containing the drive separator associated
+     *         with the current file system.
+     */
+    private String getDriveSeparator() {
+        return (dosFileSystem() ? ":" : "");
+    }
+
+    /** Returns a <code>String</code> array whose elements correspond to the
+     *  drive/directory/file components making up the <code>path</code> 
+     *  parameter.
+     *
+     *  @param path <code>String</code> containing the path/filename to parse. 
+     *
+     *  @return <code>String</code> array containing the drive/directory/file
+     *          components making up the <code>path</code> parameter.
+     */
+    private String[] getDirs(String path) {
+        String delimiter = "/\\"; // handle mixed path separators
+        StringTokenizer st = new StringTokenizer(path,delimiter);
+        int n = st.countTokens();
+        String[] strArray = new String[n];
+        for (int i = 0; (st.hasMoreTokens()) && (i < n); i++) {
+            strArray[i] = st.nextToken();
+        }
+        return strArray;
+    }
+
+    /** Determines whether the <code>path</code> parameter contains a 
+     *  drive designator, denoted by <letter A-z><:><\ or />.
+     *
+     *  @param path <code>String</code> containing the path/filename to analyze
+     *
+     *  @return <code>true</code> if the <code>path</code> parameter contains a
+     *          drive designator; <code>false</code> otherwise.
+     */
+    private boolean hasDrive(String path) {
+        char[] pathChars = path.toCharArray();
+        return ((pathChars[0] >= 'A') && 
+                (pathChars[0] <= 'z') && 
+                (pathChars[1] == ':') && 
+                ((pathChars[2] == '\\') || (pathChars[2] == '/')));
+    }
+
+    /** Determines whether or not the current file system is a DOS file system.
+     *
+     *  @return <code>true</code> if the current file system is a DOS file
+     *          system; <code>false</code> otherwise.
+     */
+    private boolean dosFileSystem() {
+        return (File.separator.equals("\\"));
+    }
+
+    /** Determines whether the <code>path</code> parameter is absolute or
+     *  relative. 
+     * 
+     *  This method applies the following criteria in making the 
+     *  determination: if the <code>path</code> parameter contains a drive
+     *  designation, the <code>path</code> parameter is always considered
+     *  absolute, regardless of the current file system. Additionally,
+     *  although the windows operating system considers a path that 
+     *  begins with two separators ('\\') absolute, and a path that begins
+     *  with only a single separator ('\') relative, this method considers
+     *  both relative. 
+     *
+     *  @param path <code>String</code> containing the path/filename to analyze
+     *
+     *  @return <code>true</code> if the <code>path</code> parameter is 
+     *          absolute; <code>false</code> otherwise.
+     */
+    private boolean isAbsolute(String path) {
+        /* A drive always means absolute no matter what file system. Also,
+         * On windows: drive or double separator ==> absolute,
+         *             but single separator ==> relative.
+         * This method considers only a drive letter absolute.
+         */
+        if (hasDrive(path)) {
+            return true;
+        }
+        if (!dosFileSystem()) {
+            return (new File(path)).isAbsolute();
+        }
+        return false;
+    }
+
+    /** Returns a <code>String</code> containing the absolute path associated
+     *  with the <code>path</code> parameter. When "computing" the absolute
+     *  path of the <code>path</code> parameter, this method considers
+     *  the current file system and whether or not the <code>path</code>
+     *  parameter contains a drive designation: if the file system does not
+     *  expect a drive designation, but the <code>path</code> parameter
+     *  contains such a drive, this method will strip off the drive designation
+     *  and return a path/filename made up with the given components
+     *  and path separators appropriate for the current file system. 
+     *
+     *  @param path <code>String</code> containing the path/filename to 
+     *              process. 
+     *
+     *  @return <code>String</code> containing the absolute path/filename
+     *          for the given <code>path</code> parameter.
+     */
+    private String getAbsolutePath(String path) {
+        if (!dosFileSystem() && hasDrive(path)) {
+            // if on unix & has a drive, strip off the drive
+            String[] components = getDirs(path);
+            StringBuffer strBuf = new StringBuffer("");
+            for (int i = 1; i < components.length; i++) {
+                strBuf.append(File.separator + components[i]);
+            }
+            return strBuf.toString();
+        }
+        return (new File(path)).getAbsolutePath();
+    }
+
+}//end class SysConfig

Propchange: river/tck/src/com/sun/jini/compat/harness/SysConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: river/tck/src/com/sun/jini/compat/harness/SysConfig.java
------------------------------------------------------------------------------
    svn:executable = *

Added: river/tck/src/com/sun/jini/compat/harness/Test.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/harness/Test.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/harness/Test.java (added)
+++ river/tck/src/com/sun/jini/compat/harness/Test.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,100 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+package com.sun.jini.compat.harness;
+
+/**
+ * This interface is implemented by all of the tests in the test harness.
+ * It provides a basic structure for each of the tests.
+ * It should be noted that there is a semantic to
+ * calling any implementation of Test:
+ * <p><ol>
+ *   <li> the constructor should be called and it should be a fairly
+ *        lightweight operation
+ *   <li> setConfig should be called to set the current Config object
+ *   <li> the setup method should be called for heavy  weight
+ *        initialization operations
+ *   <li> the run method should be called to run the test
+ *   <li> the teardown method should be called to remove anything
+ *        that the test may have left around, even if setup throws
+ *        an exception.
+ * </ol>
+ */
+public interface Test {
+    /**
+     * Provides a description of the test including both
+     * the name and the version of the test.
+     *
+     * @return the description
+     */
+    String getDescription();
+
+    /**
+     * Returns the program categories this test applies to.
+     *
+     * @return the array of categories
+     */
+    String[] getCategories();
+
+    /**
+     * Returns the administration interfaces that must be
+     * implemented by the current Admin for this test.
+     *
+     * @return the array of interfaces the admin is required to implement
+     */
+    Class[] getRequiredAdmins();
+
+    /**
+     * Sets the configuration object for this test.
+     *
+     * @param tCon the configuration object
+     */
+    void setConfig(Config tCon);
+
+    /**
+     * Gets the configuration object for this test.
+     *
+     * @return the configuration object
+     */
+    Config getConfig();
+
+    /**
+     * Performs setup for this test.  This is where any heavy
+     * weight operations should go (instead of the constructor).
+     * <p>
+     * If an exception is thrown, the tearDown method will still be called.
+     */
+    void setup(String[] args) throws Exception;
+
+    /**
+     * The semantics of the individual tests are in this method.
+     * This method must be overloaded with the semantics of the
+     * particular test.
+     *
+     * @param args command line arguments passed through to the test
+     *
+     * @return the status of this run
+     */
+    Status run(String[] args);
+
+    /**
+     * Tears down any setup that was needed to run the test.  This method is
+     * called even if setup throws an exception.
+     */
+    void tearDown();
+
+}

Propchange: river/tck/src/com/sun/jini/compat/harness/Test.java
------------------------------------------------------------------------------
    svn:eol-style = native