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 2013/02/19 11:19:40 UTC

svn commit: r1447656 - in /river/jtsk/skunk/qa_refactor/trunk/src: com/sun/jini/thread/NewThreadAction.java com/sun/jini/thread/ThreadPool.java net/jini/discovery/DiscoveryEvent.java net/jini/discovery/LookupDiscovery.java

Author: peter_firmstone
Date: Tue Feb 19 10:19:39 2013
New Revision: 1447656

URL: http://svn.apache.org/r1447656
Log:
Minor refactoring

Modified:
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/NewThreadAction.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java
    river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/DiscoveryEvent.java
    river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/LookupDiscovery.java

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/NewThreadAction.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/NewThreadAction.java?rev=1447656&r1=1447655&r2=1447656&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/NewThreadAction.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/NewThreadAction.java Tue Feb 19 10:19:39 2013
@@ -1,137 +1,137 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.jini.thread;
-
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.PrivilegedAction;
-
-/**
- * A PrivilegedAction for creating a new thread conveniently with an
- * AccessController.doPrivileged or Security.doPrivileged.
- *
- * All constructors allow the choice of the Runnable for the new
- * thread to execute, the name of the new thread (which will be
- * prefixed with the constant NAME_PREFIX), and whether or not it will
- * be a daemon thread.
- *
- * The new thread may be created in the system thread group (the root
- * of the thread group tree) or an internally created non-system
- * thread group, as specified at construction of this class.
- *
- * The new thread will have the system class loader as its initial
- * context class loader (that is, its context class loader will NOT be
- * inherited from the current thread).
- *
- * @author	Sun Microsystems, Inc.
- **/
-public final class NewThreadAction implements PrivilegedAction {
-
-    static final String NAME_PREFIX = "(JSK) ";
-
-    /** cached reference to the system (root) thread group */
-    static final ThreadGroup systemThreadGroup = (ThreadGroup)
-	AccessController.doPrivileged(new PrivilegedAction() {
-	    public Object run() {
-		ThreadGroup group = Thread.currentThread().getThreadGroup();
-		ThreadGroup parent;
-		while ((parent = group.getParent()) != null) {
-		    group = parent;
-		}
-		return group;
-	    }
-	});
-
-    /**
-     * special child of the system thread group for running tasks that
-     * may execute user code, so that the security policy for threads in
-     * the system thread group will not apply
-     */
-    static final ThreadGroup userThreadGroup = (ThreadGroup)
-	AccessController.doPrivileged(new PrivilegedAction() {
-	    public Object run() {
-		return new ThreadGroup(systemThreadGroup,
-				       NAME_PREFIX + "Runtime");
-	    }
-	});
-
-    private static final Permission getClassLoaderPermission =
-	new RuntimePermission("getClassLoader");
-
-    private final ThreadGroup group;
-    private final Runnable runnable;
-    private final String name;
-    private final boolean daemon;
-
-    NewThreadAction(ThreadGroup group, Runnable runnable,
-		    String name, boolean daemon)
-    {
-	this.group = group;
-	this.runnable = runnable;
-	this.name = name;
-	this.daemon = daemon;
-    }
-
-    /**
-     * Creates an action that will create a new thread in the
-     * system thread group.
-     *
-     * @param	runnable the Runnable for the new thread to execute
-     *
-     * @param	name the name of the new thread
-     *
-     * @param	daemon if true, new thread will be a daemon thread;
-     * if false, new thread will not be a daemon thread
-     */
-    public NewThreadAction(Runnable runnable, String name, boolean daemon) {
-	this(systemThreadGroup, runnable, name, daemon);
-    }
-
-    /**
-     * Creates an action that will create a new thread.
-     *
-     * @param	runnable the Runnable for the new thread to execute
-     *
-     * @param	name the name of the new thread
-     *
-     * @param	daemon if true, new thread will be a daemon thread;
-     * if false, new thread will not be a daemon thread
-     *
-     * @param	user if true, thread will be created in a non-system
-     * thread group; if false, thread will be created in the system
-     * thread group
-     */
-    public NewThreadAction(Runnable runnable, String name, boolean daemon,
-			   boolean user)
-    {
-	this(user ? userThreadGroup : systemThreadGroup,
-	     runnable, name, daemon);
-    }
-
-    public Object run() {
-	SecurityManager sm = System.getSecurityManager();
-	if (sm != null) {
-	    sm.checkPermission(getClassLoaderPermission);
-	}
-	Thread t = new Thread(group, runnable, NAME_PREFIX + name);
-	t.setContextClassLoader(ClassLoader.getSystemClassLoader());
-	t.setDaemon(daemon);
-	return t;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.jini.thread;
+
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+
+/**
+ * A PrivilegedAction for creating a new thread conveniently with an
+ * AccessController.doPrivileged or Security.doPrivileged.
+ *
+ * All constructors allow the choice of the Runnable for the new
+ * thread to execute, the name of the new thread (which will be
+ * prefixed with the constant NAME_PREFIX), and whether or not it will
+ * be a daemon thread.
+ *
+ * The new thread may be created in the system thread group (the root
+ * of the thread group tree) or an internally created non-system
+ * thread group, as specified at construction of this class.
+ *
+ * The new thread will have the system class loader as its initial
+ * context class loader (that is, its context class loader will NOT be
+ * inherited from the current thread).
+ *
+ * @author	Sun Microsystems, Inc.
+ **/
+public final class NewThreadAction implements PrivilegedAction<Thread> {
+
+    static final String NAME_PREFIX = "(JSK) ";
+
+    /** cached reference to the system (root) thread group */
+    static final ThreadGroup systemThreadGroup =
+	AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
+	    public ThreadGroup run() {
+		ThreadGroup group = Thread.currentThread().getThreadGroup();
+		ThreadGroup parent;
+		while ((parent = group.getParent()) != null) {
+		    group = parent;
+		}
+		return group;
+	    }
+	});
+
+    /**
+     * special child of the system thread group for running tasks that
+     * may execute user code, so that the security policy for threads in
+     * the system thread group will not apply
+     */
+    static final ThreadGroup userThreadGroup = 
+        AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
+               public ThreadGroup run() {
+		return new ThreadGroup(systemThreadGroup,
+				       NAME_PREFIX + "Runtime");
+	    }
+	});
+
+    private static final Permission getClassLoaderPermission =
+	new RuntimePermission("getClassLoader");
+
+    private final ThreadGroup group;
+    private final Runnable runnable;
+    private final String name;
+    private final boolean daemon;
+
+    NewThreadAction(ThreadGroup group, Runnable runnable,
+		    String name, boolean daemon)
+    {
+	this.group = group;
+	this.runnable = runnable;
+	this.name = name;
+	this.daemon = daemon;
+    }
+
+    /**
+     * Creates an action that will create a new thread in the
+     * system thread group.
+     *
+     * @param	runnable the Runnable for the new thread to execute
+     *
+     * @param	name the name of the new thread
+     *
+     * @param	daemon if true, new thread will be a daemon thread;
+     * if false, new thread will not be a daemon thread
+     */
+    public NewThreadAction(Runnable runnable, String name, boolean daemon) {
+	this(systemThreadGroup, runnable, name, daemon);
+    }
+
+    /**
+     * Creates an action that will create a new thread.
+     *
+     * @param	runnable the Runnable for the new thread to execute
+     *
+     * @param	name the name of the new thread
+     *
+     * @param	daemon if true, new thread will be a daemon thread;
+     * if false, new thread will not be a daemon thread
+     *
+     * @param	user if true, thread will be created in a non-system
+     * thread group; if false, thread will be created in the system
+     * thread group
+     */
+    public NewThreadAction(Runnable runnable, String name, boolean daemon,
+			   boolean user)
+    {
+	this(user ? userThreadGroup : systemThreadGroup,
+	     runnable, name, daemon);
+    }
+
+    public Thread run() {
+	SecurityManager sm = System.getSecurityManager();
+	if (sm != null) {
+	    sm.checkPermission(getClassLoaderPermission);
+	}
+	Thread t = new Thread(group, runnable, NAME_PREFIX + name);
+	t.setContextClassLoader(ClassLoader.getSystemClassLoader());
+	t.setDaemon(daemon);
+	return t;
+    }
+}

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java?rev=1447656&r1=1447655&r2=1447656&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/thread/ThreadPool.java Tue Feb 19 10:19:39 2013
@@ -1,172 +1,207 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.sun.jini.thread;
-
-import com.sun.jini.action.GetLongAction;
-import java.security.AccessController;
-import java.util.LinkedList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * ThreadPool is a simple thread pool implementation of the Executor
- * interface.
- *
- * A new task is always given to an idle thread, if one is available;
- * otherwise, a new thread is always created.  There is no minimum
- * warm thread count, nor is there a maximum thread count (tasks are
- * never queued unless there are sufficient idle threads to execute
- * them).
- *
- * New threads are created as daemon threads in the thread group that
- * was passed to the ThreadPool instance's constructor.  Each thread's
- * name is the prefix NewThreadAction.NAME_PREFIX followed by the name
- * of the task it is currently executing, or "Idle" if it is currently
- * idle.
- *
- * <p>This implementation uses the {@link Logger} named
- * <code>com.sun.jini.thread.ThreadPool</code> to
- * log information at the following levels:
- *
- * <p><table summary="Describes what is logged by ThreadPool at
- * various logging levels" border=1 cellpadding=5>
- *
- * <tr> <th> Level <th> Description
- *
- * <tr> <td> {@link Level#WARNING WARNING} <td> uncaught exception in
- * worker thread
- *
- * </table>
- *
- * @author	Sun Microsystems, Inc.
- **/
-final class ThreadPool implements Executor, java.util.concurrent.Executor {
-
-    /** how long a thread waits in the idle state before passing away */
-    private static final long idleTimeout =		// default 5 minutes
-	((Long) AccessController.doPrivileged(new GetLongAction(
-	    "com.sun.jini.thread.idleThreadTimeout", 300000)))
-	    .longValue();
-
-    private static final Logger logger =
-	Logger.getLogger("com.sun.jini.thread.ThreadPool");
-
-    /** thread group that this pool's threads execute in */
-    private final ThreadGroup threadGroup;
-
-    /** lock guarding all mutable instance state (below) */
-    private final Object lock = new Object();
-
-    /** threads definitely available to take new tasks */
-    private int idleThreads = 0;
-
-    /** queues of tasks to execute */
-    private final LinkedList queue = new LinkedList();
-
-    /**
-     * Creates a new thread group that executes tasks in threads of
-     * the given thread group.
-     */
-    ThreadPool(ThreadGroup threadGroup) {
-	this.threadGroup = threadGroup;
-    }
-
-    public void execute(Runnable runnable, String name) {
-	Task task = new Task(runnable, name);
-	synchronized (lock) {
-	    if (queue.size() < idleThreads) {
-		queue.addLast(task);
-		lock.notify();
-		return;
-	    }
-	}
-	Thread t = (Thread) AccessController.doPrivileged(
-	    new NewThreadAction(threadGroup, new Worker(task), name, true));
-	t.start();
-    }
-
-    public void execute(Runnable command) {
-        execute(command, "com.sun.jini.thread.ThreadPool");
-    }
-
-    /**
-     * Task simply encapsulates a task's Runnable object with its name.
-     */
-    private static class Task {
-
-	final Runnable runnable;
-	final String name;
-
-	Task(Runnable runnable, String name) {
-	    this.runnable = runnable;
-	    this.name = name;
-	}
-    }
-
-    /**
-     * Worker executes an initial task, and then it executes tasks from the
-     * queue, passing away if ever idle for more than the idle timeout value.
-     */
-    private class Worker implements Runnable {
-
-	private Task first;
-
-	Worker(Task first) {
-	    this.first = first;
-	}
-
-	public void run() {
-	    Task task = first;
-	    first = null;
-
-	    while (true) {
-		try {
-		    task.runnable.run();
-		} catch (Throwable t) {
-		    logger.log(Level.WARNING, "uncaught exception", t);
-		}
-		/*
-		 * REMIND: What if the task changed this thread's
-		 * priority? or context class loader?
-		 */
-
-		synchronized (lock) {
-		    if (queue.isEmpty()) {
-			Thread.currentThread().setName(
-			    NewThreadAction.NAME_PREFIX + "Idle");
-			idleThreads++;
-			try {
-			    lock.wait(idleTimeout);
-			} catch (InterruptedException e) {
-			    // ignore interrupts at this level
-			} finally {
-			    idleThreads--;
-			}
-			if (queue.isEmpty()) {
-			    break;		// timed out
-			}
-		    }
-		    task = (Task) queue.removeFirst();
-		    Thread.currentThread().setName(
-			NewThreadAction.NAME_PREFIX + task.name);
-		}
-	    };
-	}
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.jini.thread;
+
+import com.sun.jini.action.GetLongAction;
+import java.security.AccessController;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * ThreadPool is a simple thread pool implementation of the Executor
+ * interface.
+ *
+ * A new task is always given to an idle thread, if one is available;
+ * otherwise, a new thread is always created.  There is no minimum
+ * warm thread count, nor is there a maximum thread count (tasks are
+ * never queued unless there are sufficient idle threads to execute
+ * them).
+ *
+ * New threads are created as daemon threads in the thread group that
+ * was passed to the ThreadPool instance's constructor.  Each thread's
+ * name is the prefix NewThreadAction.NAME_PREFIX followed by the name
+ * of the task it is currently executing, or "Idle" if it is currently
+ * idle.
+ *
+ * <p>This implementation uses the {@link Logger} named
+ * <code>com.sun.jini.thread.ThreadPool</code> to
+ * log information at the following levels:
+ *
+ * <p><table summary="Describes what is logged by ThreadPool at
+ * various logging levels" border=1 cellpadding=5>
+ *
+ * <tr> <th> Level <th> Description
+ *
+ * <tr> <td> {@link Level#WARNING WARNING} <td> uncaught exception in
+ * worker thread
+ *
+ * </table>
+ *
+ * @author	Sun Microsystems, Inc.
+ **/
+final class ThreadPool implements Executor, java.util.concurrent.Executor {
+
+    /** how long a thread waits in the idle state before passing away */
+    private static final long idleTimeout =		// default 5 minutes
+	((Long) AccessController.doPrivileged(new GetLongAction(
+	    "com.sun.jini.thread.idleThreadTimeout", 300000)))
+	    .longValue();
+
+    private static final Logger logger =
+	Logger.getLogger("com.sun.jini.thread.ThreadPool");
+
+    /** thread group that this pool's threads execute in */
+    private final ThreadGroup threadGroup;
+
+    /** Lock used to wake idle threads and synchronize writes to idleThreads */
+    private final Lock lock;
+    private final Condition wakeup;
+
+    /** threads definitely available to take new tasks */
+    private volatile int idleThreads;
+
+    /** queues of tasks to execute */
+    private final Queue<Runnable> queue;
+
+    /**
+     * Creates a new thread group that executes tasks in threads of
+     * the given thread group.
+     */
+    ThreadPool(ThreadGroup threadGroup) {
+	this.threadGroup = threadGroup;
+        idleThreads = 0;
+        queue = new ConcurrentLinkedQueue<Runnable>(); //Non blocking queue.
+        lock = new ReentrantLock();
+        wakeup = lock.newCondition();
+    }
+
+    // This method must not block - Executor
+    public void execute(Runnable runnable, String name) {
+	Runnable task = new Task(runnable, name);
+        if (idleThreads < 3){ // create a new thread, non blocking approximate
+            Thread t = AccessController.doPrivileged(
+	    new NewThreadAction(threadGroup, new Worker(task), name, true));
+	t.start();
+        } else {
+            boolean accepted = queue.offer(task); //non blocking.
+            if (accepted) { 
+                lock.lock(); // blocking.
+                try {
+                    wakeup.signal(); 
+                } finally {
+                    lock.unlock();
+	    }
+            } else { // Should never happen.
+                Thread t = AccessController.doPrivileged(
+	    new NewThreadAction(threadGroup, new Worker(task), name, true));
+	t.start();
+    }
+        }
+    }
+
+    public void execute(Runnable command) {
+        execute(command, "com.sun.jini.thread.ThreadPool");
+    }
+
+    /**
+     * Task simply encapsulates a task's Runnable object with its name.
+     */
+    private static class Task implements Runnable{
+
+	private final Runnable runnable;
+	private final String name;
+
+	Task(Runnable runnable, String name) {
+	    this.runnable = runnable;
+	    this.name = name;
+	}
+        
+        public void run(){
+            try {
+                runnable.run();
+            } catch (Exception t) { // Don't catch Error
+                logger.log(Level.WARNING, "uncaught exception", t);
+                if (t instanceof RuntimeException){
+                    if (t instanceof SecurityException){
+                        // ignore it will be logged.
+                    } else {
+                        // Ignorance of RuntimeException is generally bad, bail out.
+                        throw (RuntimeException) t;
+    }
+                }
+            }
+        }
+
+        public String toString(){
+            return name;
+        }
+    }
+
+    /**
+     * Worker executes an initial task, and then it executes tasks from the
+     * queue, passing away if ever idle for more than the idle timeout value.
+     */
+    private class Worker implements Runnable {
+
+	private volatile Runnable first;
+
+	Worker(Runnable first) {
+	    this.first = first;
+	}
+
+	public void run() {
+	    Runnable task = first;
+	    first = null; // For garbage collection.
+            task.run();
+            Thread thread = Thread.currentThread();
+	    while (!thread.isInterrupted()) {
+		/*
+		 * REMIND: What if the task changed this thread's
+		 * priority? or context class loader?
+		 */
+                for ( task = queue.poll(); task != null; task = queue.poll()){
+                    // Keep executing while tasks are available.
+                    thread.setName(NewThreadAction.NAME_PREFIX + task);
+                    task.run();
+                }
+                // queue is empty;
+                thread.setName(NewThreadAction.NAME_PREFIX + "Idle");
+                lock.lock();
+			try {
+                    idleThreads++;
+                    wakeup.await(idleTimeout, TimeUnit.MILLISECONDS);// releases lock and obtains when woken.
+                    // Allow thread to expire if queue empty after waking.
+                    if (queue.peek() == null) thread.interrupt();
+                } catch (InterruptedException ex) {
+                    // Interrupt thread, another thread can pick up tasks.
+                    thread.interrupt();
+			} finally {
+			    idleThreads--;
+                    lock.unlock();
+			}
+			}
+		    }
+		}
+	}

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/DiscoveryEvent.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/DiscoveryEvent.java?rev=1447656&r1=1447655&r2=1447656&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/DiscoveryEvent.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/DiscoveryEvent.java Tue Feb 19 10:19:39 2013
@@ -17,7 +17,10 @@
  */
 package net.jini.discovery;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.util.EventObject;
+import java.util.HashMap;
 import java.util.Map;
 import net.jini.core.lookup.ServiceRegistrar;
 
@@ -44,7 +47,7 @@ public class DiscoveryEvent extends Even
      *
      * @serial
      */
-    protected ServiceRegistrar[] regs;
+    private ServiceRegistrar[] regs;
 
     /**
      * Map from the registrars of this event to the groups in which each
@@ -52,7 +55,7 @@ public class DiscoveryEvent extends Even
      *
      * @serial
      */
-    protected Map groups;
+    private Map groups;
 
     /**
      * Construct a new <code>DiscoveryEvent</code> object, with the given
@@ -64,7 +67,7 @@ public class DiscoveryEvent extends Even
      */
     public DiscoveryEvent(Object source, ServiceRegistrar[] regs) {
 	super(source);
-	this.regs = regs;
+	this.regs = regs.clone();
 	this.groups = null;
     }
 
@@ -91,7 +94,7 @@ public class DiscoveryEvent extends Even
      * @return the set of registrars to which this event applies.
      */
     public ServiceRegistrar[] getRegistrars() {
-	return regs;
+	return regs.clone();
     }
 
     /**
@@ -114,6 +117,13 @@ public class DiscoveryEvent extends Even
      *          registrar.
      */
     public Map getGroups() {
-        return groups;
+        return groups != null ? new HashMap(groups) : null;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private void readObject(ObjectInputStream oin) throws IOException, ClassNotFoundException{
+        oin.defaultReadObject();
+        regs = regs.clone();
+        if (groups != null) groups = new HashMap(groups);
     }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/LookupDiscovery.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/LookupDiscovery.java?rev=1447656&r1=1447655&r2=1447656&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/LookupDiscovery.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/discovery/LookupDiscovery.java Tue Feb 19 10:19:39 2013
@@ -1796,11 +1796,11 @@ public class LookupDiscovery implements 
 							       InetAddress addr,
 							       int port)
 			{
-			    logger.log(
+                                logger.log(
 				Levels.HANDLED,
 				"Exception occured during unicast discovery " +
 				addr + ":" + port, e);
-			}
+                            } 
 		    }.getResponse(loc.getHost(),
 				      loc.getPort(),
 				      rawUnicastDiscoveryConstraints);
@@ -1875,11 +1875,6 @@ public class LookupDiscovery implements 
             logger.finest("LookupDiscovery - UnicastDiscoveryTask completed");
 	}//end run
 
-        /** Returns true if current instance must be run after task(s) in
-         *  task manager queue.
-         *  @param tasks the tasks to consider.
-         *  @param size  elements with index less than size are considered.
-         */
     }//end class UnicastDiscoveryTask
 
     /**