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/05/22 14:46:26 UTC

svn commit: r1485194 [1/2] - in /river/jtsk/skunk/qa_refactor/trunk: qa/ qa/src/com/sun/jini/qa/harness/ qa/src/com/sun/jini/test/impl/outrigger/transaction/ qa/src/com/sun/jini/test/share/ src/com/sun/jini/fiddler/ src/com/sun/jini/norm/ src/com/sun/j...

Author: peter_firmstone
Date: Wed May 22 12:46:25 2013
New Revision: 1485194

URL: http://svn.apache.org/r1485194
Log:
River-420 Fixes for unsafe publication during construction.

Added:
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/AbstractActivationGroup.java
      - copied, changed from r1484449, river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AbstractSharedGroup.java
      - copied, changed from r1484449, river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedGroupImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/AbstractSharedGroupInit.java
Modified:
    river/jtsk/skunk/qa_refactor/trunk/qa/   (props changed)
    river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/KillerImpl.java
    river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/NonActivatableGroupImpl.java
    river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/transaction/SimpleEventListener.java
    river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/DiscoveryServiceUtil.java
    river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/LeaseBackEndImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ActivatableNormServerImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/NormServerBaseImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerWrapper.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/SharedGroupImpl.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/start/Starter.java

Propchange: river/jtsk/skunk/qa_refactor/trunk/qa/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed May 22 12:46:25 2013
@@ -1,6 +1,7 @@
+hs_err_pid4712.log
 classes
-lib-ext
 result
+lib-ext
 lib
 build.properties
 riverruntimelastbuild

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/KillerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/KillerImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/KillerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/KillerImpl.java Wed May 22 12:46:25 2013
@@ -25,6 +25,7 @@ import java.rmi.MarshalledObject;
 import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
+import java.rmi.server.ExportException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -51,10 +52,10 @@ class KillerImpl 
         Logger.getLogger("com.sun.jini.qa.harness");
 
     /** The inner proxy of this server */
-    private final Remote ourStub;
+    private Remote ourStub; 
 
     /** The exporter */
-    Exporter exporter;
+    final Exporter exporter;
 
     /**
      * Shared activation constructor required by the 
@@ -66,13 +67,29 @@ class KillerImpl 
     public KillerImpl(ActivationID activationID, MarshalledObject data)
 	throws IOException, ClassNotFoundException
     {
-	logger.log(Level.INFO, "Starting VMKiller service");
-	exporter = 
+	this(getExporter(activationID));
+        // Before we call export, the final freeze has occurred after calling
+        // our private constructor, we are also synchronized during export.
+        export();
+    }
+    
+    private KillerImpl(Exporter exporter) throws
+            IOException, ClassNotFoundException
+    {
+        this.exporter = exporter;
+    }
+    
+    private static Exporter getExporter(ActivationID activationID){
+        logger.log(Level.INFO, "Starting VMKiller service");
+	return
 	    new ActivationExporter(
 		   activationID, 
 		   new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
 					 new BasicILFactory()));
-	ourStub = exporter.export(this);
+    }
+    
+    private synchronized void export() throws ExportException{
+        ourStub = exporter.export(this);
     }
 
     // inherit javadoc
@@ -81,7 +98,7 @@ class KillerImpl 
 	System.exit(0);
     }
 
-    public Object getAdmin() throws RemoteException {
+    public synchronized Object getAdmin() throws RemoteException {
 	return ourStub;
     }
 
@@ -159,7 +176,7 @@ class KillerImpl 
     }
 
     // inherit javadoc
-    public Object getProxy() {
+    public synchronized Object getProxy() {
 	return ourStub;
     }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/NonActivatableGroupImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/NonActivatableGroupImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/NonActivatableGroupImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/qa/harness/NonActivatableGroupImpl.java Wed May 22 12:46:25 2013
@@ -93,30 +93,40 @@ class NonActivatableGroupImpl {
 	private Object proxy;
 
 	/** the groups exporter */
-	private Exporter exporter;
+	private final Exporter exporter;
 
 	/** store service references here to ensure no GC interference */
-	private ArrayList serviceList = new ArrayList();
+	private final ArrayList serviceList = new ArrayList();
 
 	/**
 	 * Construct a <code>NonActivatableGroup</code>. Instances export themselves
 	 * at construction time using a <code>JrmpExporter</code>.
 	 */
 	public GroupImpl() {
-	    exporter = new JrmpExporter();
-	    try {
-		proxy = exporter.export(this);
+            this (new JrmpExporter());
+	    export();
+	}
+        
+        private GroupImpl(Exporter exporter){
+           this.exporter = exporter;
+        }
+        
+        private void export(){
+            try {
+                synchronized (this){
+                    proxy = exporter.export(this);
+                }
 	    } catch (ExportException e) {
 		e.printStackTrace();
 		try {Thread.sleep(5000);} catch (Exception e2){}
 		throw new RuntimeException("Export of group failed", e);
 	    }
-	}
-
+        }
+        
 	/**
 	 * Return the proxy for the NonActivatableGroup remote object
 	 */
-	Object getProxy() {
+	synchronized Object getProxy() {
 	     return proxy;
 	}
 
@@ -180,7 +190,9 @@ class NonActivatableGroupImpl {
 	    }
 	    try {
 		Created created = (Created) desc.create(starterConfig);
-		serviceList.add(created);
+                synchronized (this){
+                    serviceList.add(created);
+                }
 		return created.proxy;
 	    } catch (Exception e) {
 		throw new RemoteException("Create failed", e);
@@ -193,7 +205,7 @@ class NonActivatableGroupImpl {
      */
     private static class DestroyThread extends Thread {
 	
-	Exporter exporter;
+	final Exporter exporter;
 
         /** Create a non-daemon thread */
         public DestroyThread(Exporter exporter) {

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/transaction/SimpleEventListener.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/transaction/SimpleEventListener.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/transaction/SimpleEventListener.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/transaction/SimpleEventListener.java Wed May 22 12:46:25 2013
@@ -34,6 +34,7 @@ import net.jini.security.proxytrust.Serv
 import com.sun.jini.proxy.BasicProxyTrustVerifier;
 
 import com.sun.jini.qa.harness.QAConfig;
+import java.rmi.server.ExportException;
 
 /**
  * Simple event listener class.
@@ -46,25 +47,40 @@ public class SimpleEventListener
 {
     private long maxSeqNum = 0;
     private Object proxy;
+    private final Exporter exporter;
 
     public SimpleEventListener(Configuration c) throws RemoteException {
-	try {
+	this(getExporter(c));
+        // 
+        export();
+    }
+    
+    private SimpleEventListener(Exporter exporter){
+        this.exporter = exporter;
+    }
+    
+    private static Exporter getExporter(Configuration c) throws RemoteException {
+        try {
 	    Exporter exporter = QAConfig.getDefaultExporter();
 	    if (c instanceof com.sun.jini.qa.harness.QAConfiguration) {
 		exporter =
 		(Exporter) c.getEntry("test", "outriggerListenerExporter", Exporter.class);
 	    }
-	    proxy = exporter.export(this);
+            return exporter;
 	} catch (ConfigurationException e) {
 	    throw new IllegalArgumentException("Bad configuration" + e);
 	}
     }
+    
+    private synchronized void export() throws ExportException{
+        proxy = exporter.export(this);
+    }
 
-    public Object writeReplace() throws ObjectStreamException {
+    public synchronized Object writeReplace() throws ObjectStreamException {
 	return proxy;
     }
 
-    public TrustVerifier getProxyVerifier() {
+    public synchronized TrustVerifier getProxyVerifier() {
 	return new BasicProxyTrustVerifier(proxy);
     }
 
@@ -74,7 +90,7 @@ public class SimpleEventListener
      *
      * @param ev Remote event object.
      */
-    public void notify(RemoteEvent ev) throws RemoteException {
+    public synchronized void notify(RemoteEvent ev) throws RemoteException {
         maxSeqNum = Math.max(ev.getSequenceNumber(), maxSeqNum);
     }
 
@@ -83,7 +99,7 @@ public class SimpleEventListener
      *
      * @return number of <code>notify</code> called.
      */
-    public long getNotifyCount(EventRegistration reg) {
+    public synchronized long getNotifyCount(EventRegistration reg) {
         return (maxSeqNum - reg.getSequenceNumber());
     }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/DiscoveryServiceUtil.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/DiscoveryServiceUtil.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/DiscoveryServiceUtil.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/DiscoveryServiceUtil.java Wed May 22 12:46:25 2013
@@ -79,17 +79,19 @@ public class DiscoveryServiceUtil {
 		    throw new RemoteException("Configuration problem", e);
 		}
 	    }
-	    proxy = exporter.export(this);
+            synchronized (this){
+                proxy = exporter.export(this);
+            }
         }
 
-	private Object writeReplace() throws ObjectStreamException {
+	private synchronized Object writeReplace() throws ObjectStreamException {
 	    return proxy;
 	}
 
         public void notify(RemoteEvent ev) {
         }
 
-	public TrustVerifier getProxyVerifier() {
+	public synchronized TrustVerifier getProxyVerifier() {
 	    return new BasicProxyTrustVerifier(proxy);
 	}
     }//end class BasicEventListener

Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/LeaseBackEndImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/LeaseBackEndImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/LeaseBackEndImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/share/LeaseBackEndImpl.java Wed May 22 12:46:25 2013
@@ -31,6 +31,7 @@ import java.io.Serializable;
 
 import com.sun.jini.qa.harness.QATestEnvironment;
 import com.sun.jini.qa.harness.QAConfig;
+import java.rmi.server.ExportException;
 
 import net.jini.export.Exporter;
 import net.jini.config.Configuration;
@@ -63,7 +64,10 @@ public class LeaseBackEndImpl implements
     /**
      * The TestLease factory used to create TestLease instances
      */
-    final private AbstractTestLeaseFactory testLeaseFactory;
+    private AbstractTestLeaseFactory testLeaseFactory;
+    
+    final private Exporter exporter;
+    final private Class factoryClass;
 
     /**
      * Simple constructor
@@ -106,7 +110,12 @@ public class LeaseBackEndImpl implements
 		throw new RemoteException("Configuration error", e);
 	    }
 	}
-	LeaseBackEnd stub = 
+	this.exporter = exporter;
+        this.factoryClass = factoryClass;
+    }
+    
+    private synchronized void export() throws ExportException, RemoteException {
+        LeaseBackEnd stub = 
 	    (LeaseBackEnd) exporter.export(this);
 
 	// create the lease factory
@@ -139,13 +148,8 @@ public class LeaseBackEndImpl implements
     } 
 
     /** Return the array of owners */
-    public LeaseOwner[] getOwners() {
-	return owners;
-    }
-
-    /** Return the array of leases */
-    TestLease[] getLeases() {
-	return leases;
+    public synchronized LeaseOwner[] getOwners() {
+	return owners.clone();
     }
 
     // inherit doc comment

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java Wed May 22 12:46:25 2013
@@ -385,6 +385,8 @@ class FiddlerImpl implements ServerProxy
     private boolean persistent;
     private LocalLogHandler logHandler;
     private AccessControlContext context;
+    
+    private boolean started;
 
     /* ************************* BEGIN Constructors ************************ */
     /**
@@ -5154,8 +5156,12 @@ class FiddlerImpl implements ServerProxy
     /* **************** END Private Static Utility Methods ***************** */
     
     /* BEGIN public start method*/
-    public void start() throws Exception 
+    public void start() throws IOException, ActivationException, ConfigurationException, LoginException, ClassNotFoundException 
     {
+        synchronized (this){
+            if (started) return;
+            started = true;
+        }
         try {
         AccessController.doPrivileged(new PrivilegedExceptionAction(){
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ActivatableNormServerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ActivatableNormServerImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ActivatableNormServerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ActivatableNormServerImpl.java Wed May 22 12:46:25 2013
@@ -46,10 +46,10 @@ import net.jini.security.ProxyPreparer;
  */
 class ActivatableNormServerImpl extends NormServerBaseImpl {
     /** Our activation ID */
-    private ActivationID activationID;
+    private final ActivationID activationID;
 
     /** The activation system, prepared */
-    private ActivationSystem activationSystem;
+    private final ActivationSystem activationSystem;
 
     // Inherit java doc from super type
     public void destroy() throws RemoteException {

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/NormServerBaseImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/NormServerBaseImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/NormServerBaseImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/NormServerBaseImpl.java Wed May 22 12:46:25 2013
@@ -245,6 +245,8 @@ abstract class NormServerBaseImpl
      *  set to null at completion of start() */
     private AccessControlContext context;
     private Configuration config;
+    
+    private boolean started;
 
     ////////////////////////////////
     // Methods defined in NormServer
@@ -1828,6 +1830,10 @@ abstract class NormServerBaseImpl
     }
     
     public void start() throws Exception {
+        synchronized (this){
+            if (started) return;
+            started = true;
+        }
         try {
             AccessController.doPrivileged(new PrivilegedExceptionAction(){
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerImpl.java Wed May 22 12:46:25 2013
@@ -79,6 +79,7 @@ import java.rmi.UnmarshalException;
 import java.rmi.activation.ActivationID;
 import java.rmi.activation.ActivationSystem;
 import java.rmi.activation.ActivationException;
+import java.rmi.server.ExportException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.SecureRandom;
@@ -641,7 +642,7 @@ public class OutriggerServerImpl 
         }
     }
     
-    public void start() throws Exception {
+    public void start() throws IOException, ConfigurationException, LoginException {
         // Threads are created with login context if it exists, but started in
         // privileged context.
         synchronized (this){
@@ -649,12 +650,18 @@ public class OutriggerServerImpl 
             started = true;
         }
         if (thrown != null) throw (Error) thrown;
-        if (except != null) throw except;
+        if (except != null){
+            if (except instanceof IOException) throw (IOException) except;
+            else if (except instanceof ConfigurationException) throw (ConfigurationException) except;
+            else if (except instanceof LoginException) throw (LoginException) except;
+            else if (except instanceof RuntimeException) throw (RuntimeException) except;
+        }
+   
         try {
             AccessController.doPrivileged(new PrivilegedExceptionAction(){
 
                 @Override
-                public Object run() throws Exception {
+                public Object run() throws ExportException, ConfigurationException, IOException {
                     ourRemoteRef = (OutriggerServer) exporter.export(serverGate);
                             // This takes a while the first time, so let's get it going
                     txnMonitor.start();
@@ -729,7 +736,8 @@ public class OutriggerServerImpl 
                 
             }, context);
             
-        } catch (Exception e) {
+        } catch (PrivilegedActionException ex) {
+            Exception e = ex.getException();
             // Clean up and rethrow.
             lifecycleLogger.log(Level.SEVERE, "Failed to start Outrigger server", e);
            
@@ -782,7 +790,10 @@ public class OutriggerServerImpl 
                     // Ignore and go on
                 }
             }
-            throw e;
+            if (e instanceof IOException) throw (IOException) e;
+            else if (e instanceof ConfigurationException) throw (ConfigurationException) e;
+            else if (e instanceof LoginException) throw (LoginException) e;
+            else if (e instanceof RuntimeException) throw (RuntimeException) e;
         } finally {
             config = null;
             starter = null;

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerWrapper.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerWrapper.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerWrapper.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/outrigger/OutriggerServerWrapper.java Wed May 22 12:46:25 2013
@@ -486,7 +486,7 @@ class OutriggerServerWrapper 
 	return delegate.getProxyVerifier();
     }
 
-    public void start() throws Exception {
-        ((Starter) delegate).start();
+    public void start() throws IOException, ConfigurationException, LoginException {
+        delegate.start();
     }
 }

Copied: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/AbstractActivationGroup.java (from r1484449, river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java)
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/AbstractActivationGroup.java?p2=river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/AbstractActivationGroup.java&p1=river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java&r1=1484449&r2=1485194&rev=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/AbstractActivationGroup.java Wed May 22 12:46:25 2013
@@ -39,6 +39,7 @@ import java.rmi.activation.ActivationID;
 import java.rmi.activation.ActivationInstantiator;
 import java.rmi.activation.ActivationMonitor;
 import java.rmi.activation.ActivationSystem;
+import java.rmi.activation.UnknownGroupException;
 import java.rmi.activation.UnknownObjectException;
 import java.rmi.server.ExportException;
 import java.rmi.server.RMIClassLoader;
@@ -204,7 +205,7 @@ import net.jini.security.proxytrust.Serv
  * 
  * @since 2.0
  **/
-public class ActivationGroupImpl extends ActivationGroup
+abstract class AbstractActivationGroup extends ActivationGroup
     implements ServerProxyTrust
 {
     private static final long serialVersionUID = 5758693559430427303L;
@@ -350,7 +351,7 @@ public class ActivationGroupImpl extends
 			unexportWait = getInt(config, "unexportWait", 10);
 			ActivationSystem sys = (ActivationSystem)
 			    sysPreparer.prepareProxy(id.getSystem());
-			ActivationGroupImpl.incarnation = incarnation;
+			AbstractActivationGroup.incarnation = incarnation;
 			groupID = id;
 			state = CREATING;
 			ActivationGroupID gid = (sys == id.getSystem() ?
@@ -380,7 +381,7 @@ public class ActivationGroupImpl extends
 	throws ConfigurationException, IOException, ClassNotFoundException
     {
 	ActivationGroupData data = (ActivationGroupData) mobj.get();
-	ClassLoader cl = ActivationGroupImpl.class.getClassLoader();
+	ClassLoader cl = AbstractActivationGroup.class.getClassLoader();
 	ClassLoader ccl = Thread.currentThread().getContextClassLoader();
 	if (!covers(cl, ccl)) {
 	    cl = ccl;
@@ -428,6 +429,7 @@ public class ActivationGroupImpl extends
 	return ((Integer) config.getEntry(PHOENIX, name, int.class,
 					  Integer.valueOf(defValue))).intValue();
     }
+    private final ActivationGroupID id;
 
     /**
      * ActivationGroupID containing a prepared ActivationSystem proxy and
@@ -485,34 +487,48 @@ public class ActivationGroupImpl extends
      * @throws ActivationException if the constructor was not called
      * indirectly from <code>createGroup</code>
      */
-    public ActivationGroupImpl(ActivationGroupID id, MarshalledObject data)
+    AbstractActivationGroup(ActivationGroupID id, MarshalledObject data)
 	throws ActivationException, RemoteException
     {
 	super(id);
-	synchronized (ActivationGroupImpl.class) {
+        this.id = id;
+	synchronized (AbstractActivationGroup.class) {
 	    if (state != CREATING) {
 		throw new ActivationException("not called from createGroup");
 	    }
 	}
-	if (refuseCalls) {
-	    unexportObject(this, true);
-	    refuseCalls = false;
-	}
-	proxy = (ActivationInstantiator) exporter.export(this);
-	try {
-	    monitor = (ActivationMonitor) monPreparer.prepareProxy(
-			  id.getSystem().activeGroup(id, proxy, incarnation));
-	    state = CREATED;
-	} finally {
-	    if (state != CREATED) {
-		exporter.unexport(true);
+	
+    }
+    
+    void export() throws NoSuchObjectException, ExportException, 
+            RemoteException, UnknownGroupException, ActivationException
+    {
+        synchronized (AbstractActivationGroup.class) {
+            if (state != CREATING) {
+		throw new ActivationException("not called from createGroup");
 	    }
-	}
-	monPreparer = null;
+            if (refuseCalls) {
+                unexportObject(this, true);
+                refuseCalls = false;
+            }
+            proxy = (ActivationInstantiator) exporter.export(this);
+            try {
+                monitor = (ActivationMonitor) monPreparer.prepareProxy(
+                              id.getSystem().activeGroup(id, proxy, incarnation));
+                state = CREATED;
+            } finally {
+                if (state != CREATED) {
+                    exporter.unexport(true);
+                }
+            }
+            monPreparer = null;
+        }
     }
 
     public TrustVerifier getProxyVerifier() {
-	return new BasicProxyTrustVerifier(proxy);
+        synchronized (AbstractActivationGroup.class){
+            return new BasicProxyTrustVerifier(proxy);
+        }
     }
     
     /**
@@ -559,7 +575,9 @@ public class ActivationGroupImpl extends
      * @return the proxy for this remote object
      */
     protected Object writeReplace() {
-	return proxy;
+        synchronized (AbstractActivationGroup.class){
+            return proxy;
+        }
     }
 
     /*
@@ -682,7 +700,7 @@ public class ActivationGroupImpl extends
 					final ActivationDesc desc)
 	throws ActivationException
     {
-	synchronized (ActivationGroupImpl.class) {
+	synchronized (AbstractActivationGroup.class) {
 	    if (refuseCalls) {
 		throw new SecurityException("call refused");
 	    }
@@ -691,7 +709,7 @@ public class ActivationGroupImpl extends
 	acquireLock(id);
 	try {
 	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		if (state != ACTIVE) {
 		    throw new InactiveGroupException("group not active");
 		}
@@ -758,7 +776,7 @@ public class ActivationGroupImpl extends
 	    }
 
 	    entry = new ActiveEntry(impl);
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		active.put(id, entry);
 	    }
 	    return entry.mobj;
@@ -824,7 +842,7 @@ public class ActivationGroupImpl extends
 	acquireLock(id);
 	try {
 	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		if (state != ACTIVE) {
 		    throw new InactiveGroupException("group not active");
 		}
@@ -852,7 +870,7 @@ public class ActivationGroupImpl extends
 	    } catch (UnknownObjectException allowUnregisteredObjects) {
 	    }
 
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		active.remove(id);
 	    }
 	} finally {
@@ -902,7 +920,7 @@ public class ActivationGroupImpl extends
 	acquireLock(id);
 	try {
 	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		if (state != ACTIVE) {
 		    throw new InactiveGroupException("group not active");
 		}
@@ -927,7 +945,7 @@ public class ActivationGroupImpl extends
 	    } catch (UnknownObjectException allowUnregisteredObjects) {
 	    }
 
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		active.remove(id);
 	    }
 	} finally {
@@ -943,7 +961,7 @@ public class ActivationGroupImpl extends
      * marks it as such, notifies the daemon, and unexports the group.
      */
     private static void checkInactiveGroup() {
-	synchronized (ActivationGroupImpl.class) {
+	synchronized (AbstractActivationGroup.class) {
 	    if (state == ACTIVE) {
 		if (!active.isEmpty() || !lockedIDs.isEmpty()) {
 		    return;
@@ -1048,7 +1066,7 @@ public class ActivationGroupImpl extends
 	final ActiveEntry entry = new ActiveEntry(impl);
 	acquireLock(id);
 	try {
-	    synchronized (ActivationGroupImpl.class) {
+	    synchronized (AbstractActivationGroup.class) {
 		if (state != ACTIVE) {
 		    throw new InactiveGroupException("group not active");
 		}
@@ -1113,8 +1131,8 @@ public class ActivationGroupImpl extends
      * Entry in table for active object.
      */
     private static class ActiveEntry {
-	Remote impl;
-	MarshalledObject mobj;
+	final Remote impl;
+	final MarshalledObject mobj;
 
 	ActiveEntry(Remote impl) throws ActivationException {
 	    this.impl = impl;

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java?rev=1485194&r1=1485193&r2=1485194&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/phoenix/ActivationGroupImpl.java Wed May 22 12:46:25 2013
@@ -1,1139 +1,246 @@
-/*
- * 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.phoenix;
-
-import com.sun.jini.thread.Executor;
-import com.sun.jini.thread.GetThreadPoolAction;
-import com.sun.jini.proxy.BasicProxyTrustVerifier;
-import java.io.IOException;
-import java.io.ObjectStreamClass;
-import java.io.ObjectStreamField;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.rmi.MarshalledObject;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.activation.Activatable;
-import java.rmi.activation.ActivationDesc;
-import java.rmi.activation.ActivationException;
-import java.rmi.activation.ActivationGroupDesc;
-import java.rmi.activation.ActivationGroupID;
-import java.rmi.activation.ActivationID;
-import java.rmi.activation.ActivationInstantiator;
-import java.rmi.activation.ActivationMonitor;
-import java.rmi.activation.ActivationSystem;
-import java.rmi.activation.UnknownObjectException;
-import java.rmi.server.ExportException;
-import java.rmi.server.RMIClassLoader;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.UnicastRemoteObject;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import net.jini.activation.ActivationGroup;
-import net.jini.config.Configuration;
-import net.jini.config.ConfigurationException;
-import net.jini.config.ConfigurationProvider;
-import net.jini.export.Exporter;
-import net.jini.export.ProxyAccessor;
-import net.jini.jeri.BasicJeriExporter;
-import net.jini.jeri.tcp.TcpServerEndpoint;
-import net.jini.security.BasicProxyPreparer;
-import net.jini.security.ProxyPreparer;
-import net.jini.security.Security;
-import net.jini.security.TrustVerifier;
-import net.jini.security.proxytrust.ServerProxyTrust;
-
-/**
- * The default activation group implementation for phoenix.  Instances of
- * this class are configurable through a {@link Configuration}, as detailed
- * further below, and provide the necessary support to allow exporter-based
- * remote objects to go inactive.  Instances of this class support the
- * creation of remote objects through the normal activatable constructor;
- * an activatable remote object must either implement the {@link
- * ProxyAccessor} interface to return a suitable proxy for the remote
- * object, or the remote object must itself be serializable and marshalling
- * the object must produce a suitable proxy for the remote object.
- * 
- * <p>An instance of this class can be configured by specifying an
- * {@link ActivationGroupData} instance containing configuration options
- * as the initialization data for the activation group. Typically
- * this is accomplished indirectly, by setting the
- * <code>groupConfig</code> configuration entry for
- * phoenix itself. The following entries are obtained from the configuration,
- * all for the component named <code>com.sun.jini.phoenix</code>:
- *
- *  <table summary="Describes the loginContext configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      loginContext</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>{@link javax.security.auth.login.LoginContext}</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>null</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> JAAS login context
- *  </table>
- *
- *  <table summary="Describes the inheritGroupSubject configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      inheritGroupSubject</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>boolean</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>false</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> if <code>true</code>, group subject is inherited
- *		when an activatable object is created 
- *  </table>
- *
- *  <table summary="Describes the instantiatorExporter configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      instantiatorExporter</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>{@link net.jini.export.Exporter}</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> retains existing JRMP export of instantiator
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> {@link java.rmi.activation.ActivationInstantiator}
- *		exporter
- *  </table>
- *
- *  <table summary="Describes the monitorPreparer configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      monitorPreparer</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>{@link net.jini.security.ProxyPreparer}</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>new {@link
- *		net.jini.security.BasicProxyPreparer}()</code> 
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> {@link java.rmi.activation.ActivationMonitor}
- *		proxy preparer 
- *  </table>
- *
- *  <table summary="Describes the systemPreparer configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      systemPreparer</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>{@link net.jini.security.ProxyPreparer}</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>new {@link
- *		net.jini.security.BasicProxyPreparer}()</code> 
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> {@link java.rmi.activation.ActivationSystem}
- *		proxy preparer 
- *  </table>
- *
- *  <table summary="Describes the unexportTimeout configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      unexportTimeout</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>int</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>60000</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> maximum time in milliseconds to wait for
- *		in-progress calls to finish before forcibly unexporting the
- *		group when going inactive 
- *  </table>
- *
- *  <table summary="Describes the unexportWait configuration entry"
- *         border="0" cellpadding="2">
- *    <tr valign="top">
- *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
- *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
- *      unexportWait</code></font>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Type: <td> <code>int</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Default: <td> <code>10</code>
- *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
- *      Description: <td> milliseconds to wait between unexport attempts
- *		when going inactive 
- *  </table>
- * 
- * <p>This class depends on its {@link #createGroup createGroup} method being
- * called to initialize the activation group. As such, this class cannot be
- * used in conjunction with the standard <code>rmid</code>.
- *
- * @author Sun Microsystems, Inc.
- * 
- * @since 2.0
- **/
-public class ActivationGroupImpl extends ActivationGroup
-    implements ServerProxyTrust
-{
-    private static final long serialVersionUID = 5758693559430427303L;
-
-    private static final String PHOENIX = "com.sun.jini.phoenix";
-    /** instance has not been created */
-    private static final int UNUSED = 0;
-    /** in the middle of createGroup */
-    private static final int CREATING = 1;
-    /** constructor (including activeGroup) has succeeded */
-    private static final int CREATED = 2;
-    /** createGroup has succeeded */
-    private static final int ACTIVE = 3;
-    /** group is inactive */
-    private static final int INACTIVE = 4;
-    /** parameter types for activatable constructor */
-    private static Class[] paramTypes = {
-	ActivationID.class, MarshalledObject.class
-    };
-
-    /* avoid serial field clutter */
-    private static final ObjectStreamField[] serialPersistentFields =
-						ObjectStreamClass.NO_FIELDS;
-
-    private static int state = UNUSED;
-    private static long incarnation;
-    /** original unprepared group id */
-    private static ActivationGroupID groupID;
-
-    /** server LoginContext or null */
-    private static LoginContext login;
-    private static Exporter exporter;
-    /** true if calls should be refused, false otherwise */
-    private static boolean refuseCalls = false;
-    /** monitor proxy preparer */
-    private static ProxyPreparer monPreparer;
-    private static ActivationMonitor monitor;
-    /** timeout on wait for unexport to succeed */
-    private static long unexportTimeout;
-    /** timeout on wait between unexport attempts */
-    private static long unexportWait;
-    /** maps ActivationID to ActiveEntry */
-    private static Map active = new HashMap();
-    /** ActivationIDs with operations in progress */
-    private static List lockedIDs = new ArrayList();
-    /** true if group subject is inherited when creating activatable objects */
-    private static boolean inheritGroupSubject;
-
-    /** permission to check for monitor's activeObject call */
-    private final static Permission activeObjectPermission =
-        new MonitorPermission(
-	    "java.rmi.activation.ActivationMonitor.activeObject");
-    
-    /** permission to check for monitor's activeObject call */
-    private static Permission inactiveObjectPermission =
-        new MonitorPermission(
-	    "java.rmi.activation.ActivationMonitor.inactiveObject");
-    
-    /** proxy for this activation group */
-    private ActivationInstantiator proxy;
-
-    /**
-     * Creates an {@link java.rmi.activation.ActivationGroup} instance and
-     * returns it. An {@link ActivationGroupData} instance is extracted from
-     * the initialization data, and a {@link Configuration} is obtained by
-     * calling
-     * {@link net.jini.config.ConfigurationProvider#getInstance
-     * Configuration.Provider.getInstance} with the configuration options from
-     * that instance. A {@link LoginContext} is obtained from the
-     * <code>loginContext</code> configuration entry, if one exists; if the
-     * value is not <code>null</code>, a login is performed on that context,
-     * and the resulting {@link Subject} (set to be read-only) is used as the
-     * subject when executing the rest of this method. The subject is also
-     * used for all subsequent remote calls by this class to the
-     * {@link ActivationMonitor}. The {@link ActivationSystem} proxy
-     * (obtained from the <code>ActivationGroupID</code>) is passed to the
-     * {@link ProxyPreparer} given by the <code>systemPreparer</code>
-     * configuration entry, if one exists; a new
-     * <code>ActivationGroupID</code> is constructed with the resulting proxy.
-     * An {@link Exporter} instance is obtained from the
-     * <code>instantiatorExporter</code> configuration entry, if one exists;
-     * this exporter will be used (in the constructor of this class) to export
-     * the group. A <code>ProxyPreparer</code> instance is obtained from the
-     * <code>monitorPreparer</code> configuration entry, if one exists; this
-     * preparer will be used (in the constructor of this class) to prepare the
-     * <code>ActivationMonitor</code>. A call is then made to
-     * {@link ActivationGroup#createGroup ActivationGroup.createGroup} with
-     * the new group identifier, the activation group descriptor, and the
-     * group incarnation number, and the result of that call is returned.
-     *
-     * @param id the activation group identifier
-     * @param desc the activation group descriptor
-     * @param incarnation the group's incarnation number (zero on initial
-     * creation)
-     * @return the created activation group
-     * @throws ActivationException if a group already exists or if an
-     * exception occurs during group creation
-     */
-    public static synchronized
-	java.rmi.activation.ActivationGroup createGroup(
-					      final ActivationGroupID id,
-					      final ActivationGroupDesc desc,
-					      final long incarnation)
-        throws ActivationException
-    {
-	if (state != UNUSED) {
-	    throw new ActivationException("group previously created");
-	}
-	try {
-	    final Configuration config = getConfiguration(desc.getData());
-	    login = (LoginContext) config.getEntry(
-			PHOENIX, "loginContext", LoginContext.class, null);
-	    if (login != null) {
-		login.login();
-	    }
-		
-	    inheritGroupSubject =
-		((Boolean) config.getEntry(
-		    PHOENIX, "inheritGroupSubject", boolean.class,
-		    Boolean.FALSE)).booleanValue();
-	    
-	    return (java.rmi.activation.ActivationGroup) doAction(
-		new PrivilegedExceptionAction() {
-		    public Object run() throws Exception {
-			ProxyPreparer sysPreparer =
-			    getPreparer(config, "systemPreparer");
-			monPreparer = getPreparer(config,
-						  "monitorPreparer");
-			TcpServerEndpoint se =
-			    TcpServerEndpoint.getInstance(0);
-			Exporter defaultExporter =
-			    new BasicJeriExporter(se, new AccessILFactory());
-			exporter = (Exporter) config.getEntry(
-				PHOENIX, "instantiatorExporter",
-				Exporter.class, defaultExporter);
-			if (exporter == null) {
-			    exporter = new AlreadyExportedExporter();
-			}
-			refuseCalls =
-			    !(exporter instanceof AlreadyExportedExporter);
-			unexportTimeout = getInt(config, "unexportTimeout",
-						 60000);
-			unexportWait = getInt(config, "unexportWait", 10);
-			ActivationSystem sys = (ActivationSystem)
-			    sysPreparer.prepareProxy(id.getSystem());
-			ActivationGroupImpl.incarnation = incarnation;
-			groupID = id;
-			state = CREATING;
-			ActivationGroupID gid = (sys == id.getSystem() ?
-						 id : new WrappedGID(id, sys));
-			Object group = ActivationGroup.createGroup(
-						    gid, desc, incarnation);
-			state = ACTIVE;
-			return group;
-		    }
-		});
-	} catch (ActivationException e) {
-	    throw e;
-	} catch (Exception e) {
-	    throw new ActivationException("creation failed", e);
-	} finally {
-	    if (state != ACTIVE) {
-		checkInactiveGroup();
-	    }
-	}
-    }
-
-    /**
-     * Returns the configuration obtained from the specified marshalled
-     * object. 
-     */
-    private static Configuration getConfiguration(MarshalledObject mobj)
-	throws ConfigurationException, IOException, ClassNotFoundException
-    {
-	ActivationGroupData data = (ActivationGroupData) mobj.get();
-	ClassLoader cl = ActivationGroupImpl.class.getClassLoader();
-	ClassLoader ccl = Thread.currentThread().getContextClassLoader();
-	if (!covers(cl, ccl)) {
-	    cl = ccl;
-	}
-	return ConfigurationProvider.getInstance(data.getConfig(), cl);
-    }
-    
-    /**
-     * Returns true if the first argument is either equal to, or is a
-     * descendant of, the second argument.  Null is treated as the root of
-     * the tree.
-     */
-    private static boolean covers(ClassLoader sub, ClassLoader sup) {
-	if (sup == null) {
-	    return true;
-	} else if (sub == null) {
-	    return false;
-	}
-	do {
-	    if (sub == sup) {
-		return true;
-	    }
-	    sub = sub.getParent();
-	} while (sub != null);
-	return false;
-    }
-
-    /**
-     * Return a ProxyPreparer configuration entry.
-     */
-    private static ProxyPreparer getPreparer(Configuration config, String name)
-	throws ConfigurationException
-    {
-	return (ProxyPreparer) config.getEntry(PHOENIX, name,
-					       ProxyPreparer.class,
-					       new BasicProxyPreparer());
-    }
-
-    /**
-     * Return an int configuration entry.
-     */
-    private static int getInt(Configuration config, String name, int defValue)
-	throws ConfigurationException
-    {
-	return ((Integer) config.getEntry(PHOENIX, name, int.class,
-					  Integer.valueOf(defValue))).intValue();
-    }
-
-    /**
-     * ActivationGroupID containing a prepared ActivationSystem proxy and
-     * the original ActivationGroupID (with unprepared ActivationSystem
-     * proxy), that writeReplaces itself to the original.
-     */
-    private static class WrappedGID extends ActivationGroupID {
-	/** Original gid */
-	private final ActivationGroupID id;
-	/** Prepared system proxy */
-	private final ActivationSystem sys;
-
-	WrappedGID(ActivationGroupID id, ActivationSystem sys) {
-	    super(sys);
-	    this.id = id;
-	    this.sys = sys;
-	}
-
-	/* override */
-	public ActivationSystem getSystem() {
-	    return sys;
-	}
-
-	private Object writeReplace() {
-	    return id;
-	}
-    }
-
-    /**
-     * Creates an instance with the specified group identifier and
-     * initialization data. This constructor must be called indirectly,
-     * via {@link #createGroup createGroup}. By default, this instance
-     * automatically exports itself as a {@link UnicastRemoteObject}. (This
-     * is a limitation of the existing activation system design.) If an
-     * {@link Exporter} was obtained by {@link #createGroup createGroup},
-     * then this instance is unexported from the JRMP runtime and re-exported
-     * using that exporter. (Any incoming remote calls received on the
-     * original JRMP export before this instance can be unexported will be
-     * refused with a security exception thrown.) The
-     * {@link ActivationSystem#activeGroup activeGroup} method of the
-     * activation system proxy (in the group identifier) is called to
-     * make the group active. The returned {@link ActivationMonitor} proxy
-     * is passed to the corresponding {@link ProxyPreparer} obtained by
-     * <code>createGroup</code>. Note that after this constructor returns,
-     * {@link ActivationGroup#createGroup ActivationGroup.createGroup} will
-     * also call <code>activeGroup</code> (so the activation system must
-     * accept idempotent calls to that method), but the
-     * <code>ActivationMonitor</code> proxy returned by that call will not be
-     * used.
-     * 
-     * @param id the activation group identifier
-     * @param data group initialization data (ignored)
-     * @throws RemoteException if the group could not be exported or
-     * made active, or proxy preparation fails
-     * @throws ActivationException if the constructor was not called
-     * indirectly from <code>createGroup</code>
-     */
-    public ActivationGroupImpl(ActivationGroupID id, MarshalledObject data)
-	throws ActivationException, RemoteException
-    {
-	super(id);
-	synchronized (ActivationGroupImpl.class) {
-	    if (state != CREATING) {
-		throw new ActivationException("not called from createGroup");
-	    }
-	}
-	if (refuseCalls) {
-	    unexportObject(this, true);
-	    refuseCalls = false;
-	}
-	proxy = (ActivationInstantiator) exporter.export(this);
-	try {
-	    monitor = (ActivationMonitor) monPreparer.prepareProxy(
-			  id.getSystem().activeGroup(id, proxy, incarnation));
-	    state = CREATED;
-	} finally {
-	    if (state != CREATED) {
-		exporter.unexport(true);
-	    }
-	}
-	monPreparer = null;
-    }
-
-    public TrustVerifier getProxyVerifier() {
-	return new BasicProxyTrustVerifier(proxy);
-    }
-    
-    /**
-     * Exporter for an object that is already exported to JRMP.
-     */
-    private static class AlreadyExportedExporter implements Exporter {
-	/**
-	 * A strong reference to the impl is OK because ActivationGroup
-	 * also holds a strong reference.
-	 */
-	private Remote impl;
-
-	AlreadyExportedExporter() {
-	}
-
-	public synchronized Remote export(Remote impl) throws ExportException {
-	    this.impl = impl;
-	    try {
-		return RemoteObject.toStub(impl);
-	    } catch (NoSuchObjectException e) {
-		throw new ExportException("no stub found", e);
-	    }
-	}
-
-	public synchronized boolean unexport(boolean force) {
-	    try {
-		if (impl != null &&
-		    !UnicastRemoteObject.unexportObject(impl, force))
-		{
-		    return false;
-		}
-	    } catch (NoSuchObjectException e) {
-	    }
-	    impl = null;
-	    return true;
-	}
-    }
-
-    /**
-     * Returns the proxy for this remote object. Group creation was designed
-     * to rely on automatic stub replacement (as provided by the JRMP runtime),
-     * which is not supported by all exporters.
-     *
-     * @return the proxy for this remote object
-     */
-    protected Object writeReplace() {
-	return proxy;
-    }
-
-    /*
-     * Obtains a lock on the ActivationID id before returning. Allows only one
-     * thread at a time to hold a lock on a particular id.  If the lock for id
-     * is in use, all requests for an equivalent (in the .equals sense)
-     * id will wait for the id to be notified and use the supplied id as the
-     * next lock. The caller of "acquireLock" must execute the "releaseLock"
-     * method" to release the lock and "notifyAll" waiters for the id lock
-     * obtained from this method.  The typical usage pattern is as follows:
-     *
-     * acquireLock(id);
-     * try {
-     *    // do stuff pertaining to id...
-     * } finally {
-     *    releaseLock(id);
-     * }
-     */
-    private void acquireLock(ActivationID id) {
-	while (true) {
-	    synchronized (id) {
-		synchronized (lockedIDs) {
-		    int index = lockedIDs.indexOf(id);
-		    if (index < 0) {
-			lockedIDs.add(id);
-			return;
-		    }
-		    ActivationID lockedID =
-			(ActivationID) lockedIDs.get(index);
-		    if (lockedID != id) {
-			// don't wait on an id that won't be notified
-			id = lockedID;
-			continue;
-		    }
-		}
-		try {
-		    id.wait();
-		} catch (InterruptedException ignore) {
-		}
-	    }
-	}
-    }
-
-    /*
-     * Releases the id lock obtained via the "acquireLock" method and then
-     * notifies all threads waiting on the lock.
-     */
-    private void releaseLock(ActivationID id) {
-	synchronized (lockedIDs) {
-	    id = (ActivationID) lockedIDs.remove(lockedIDs.indexOf(id));
-	}
-	synchronized (id) {
-	    id.notifyAll();
-	}
-    }
-
-    /**
-     * Creates a new instance of an activatable remote object and returns
-     * a marshalled object containing the activated object's proxy.
-     *
-     * <p>If an active object already exists for the specified identifier,
-     * the existing marshalled object for it is returned.
-     *
-     * <p>Otherwise:
-     *
-     * <p>The class for the object is loaded by invoking {@link
-     * RMIClassLoader#loadClass(String,String) RMIClassLoader.loadClass}
-     * passing the class location (obtained by invoking {@link
-     * ActivationDesc#getLocation getLocation} on the activation
-     * descriptor) and the class name (obtained by invoking {@link
-     * ActivationDesc#getClassName getClassName} on the activation
-     * descriptor).
-     *
-     * <p>The new instance is constructed as follows. If the class defines
-     * a constructor with two parameters of type {@link ActivationID} and
-     * {@link MarshalledObject}, that constructor is called with the
-     * specified activation identifier and the initialization data from the
-     * specified activation descriptor. Otherwise, an
-     * <code>ActivationException</code> is thrown.
-     *
-     * <p>If the class loader of the object's class is a descendant of the
-     * current context class loader, then that class loader is set as the
-     * context class loader when the constructor is called.
-     *
-     * <p>If the <code>inheritGroupSubject</code> configuration entry is
-     * <code>true</code> then the constructor is invoked in an action
-     * passed to the {@link Security#doPrivileged Security.doPrivileged}
-     * method; otherwise the constructor is invoked in an action passed to
-     * the {@link AccessController#doPrivileged
-     * AccessController.doPrivileged} method.
-     *
-     * <p>A proxy for the newly created instance is returned as follows:
-     *
-     * <ul><li>If the newly created instance implements {@link
-     * ProxyAccessor}, a proxy is obtained by invoking the {@link
-     * ProxyAccessor#getProxy getProxy} method on that instance. If the
-     * obtained proxy is not <code>null</code>, that proxy is returned in a
-     * <code>MarshalledObject</code>; otherwise, an
-     * <code>ActivationException</code> is thrown.
-     *
-     * <li>If the newly created instance does not implement
-     * <code>ProxyAccessor</code>, the instance is returned in a
-     * <code>MarshalledObject</code>.  In this case, the instance must be
-     * serializable, and marshalling the instance must produce a suitable
-     * proxy for the remote object (for example, the object implements
-     * {@link java.io.Serializable} and defines a <code>writeReplace</code>
-     * method that returns the object's proxy).
-     * </ul>
-     *
-     * <p>If both the remote object and the activation group are exported
-     * using JRMP, then automatic stub replacement will produce the desired
-     * result, but otherwise the remote object implementation must provide
-     * a means for this group to obtain its proxy as indicated above.
-     *
-     * @throws ActivationException if the object's class could not be
-     * loaded, if the loaded class does not define the appropriate
-     * constructor, or any exception occurs activating the object
-     **/
-    public MarshalledObject newInstance(final ActivationID id,
-					final ActivationDesc desc)
-	throws ActivationException
-    {
-	synchronized (ActivationGroupImpl.class) {
-	    if (refuseCalls) {
-		throw new SecurityException("call refused");
-	    }
-	}
-
-	acquireLock(id);
-	try {
-	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
-		if (state != ACTIVE) {
-		    throw new InactiveGroupException("group not active");
-		}
-		entry = (ActiveEntry) active.get(id);
-	    }
-	    if (entry != null) {
-		return entry.mobj;
-	    }
-
-	    String className = desc.getClassName();
-	    final Class cl = RMIClassLoader.loadClass(desc.getLocation(),
-						      className);
-	    final Thread t = Thread.currentThread();
-	    final ClassLoader savedCcl = t.getContextClassLoader();
-	    final ClassLoader ccl =
-		covers(cl.getClassLoader(), savedCcl) ?
-		cl.getClassLoader() : savedCcl;
-
-	    Remote impl = null;
-
-	    /*
-	     * Fix for 4164971: allow non-public activatable class
-	     * and/or constructor, create the activatable object in a
-	     * privileged block
-	     */
-	    try {
-		PrivilegedExceptionAction action =
-		   new PrivilegedExceptionAction() {
-		      public Object run() throws InstantiationException,
-			  NoSuchMethodException, IllegalAccessException,
-			  InvocationTargetException, ActivationException
-		      {
-			  Object[] params = new Object[] {id, desc.getData()};
-			  Constructor constructor =
-			      cl.getDeclaredConstructor(paramTypes);
-			  constructor.setAccessible(true);
-			  try {
-			      /*
-			       * Fix for 4289544: make sure to set the
-			       * context class loader to be the class
-			       * loader of the impl class before
-			       * constructing that class.
-			       */
-			      t.setContextClassLoader(ccl);
-			      return constructor.newInstance(params);
-			  } finally {
-			      t.setContextClassLoader(savedCcl);
-			  }
-		      }
-		   };
-
-		/*
-		 * The activatable object is created is in a doPrivileged
-		 * block to protect against user code which might have set
-		 * a global socket factory (in which case application code
-		 * would be on the stack).
-		 */
-		impl = (Remote) (inheritGroupSubject ?
-				 Security.doPrivileged(action) :
-				 AccessController.doPrivileged(action));
-			
-	    } catch (PrivilegedActionException pae) {
-		throw pae.getException();
-	    }
-
-	    entry = new ActiveEntry(impl);
-	    synchronized (ActivationGroupImpl.class) {
-		active.put(id, entry);
-	    }
-	    return entry.mobj;
-	} catch (NoSuchMethodException e) {
-	    /* user forgot to provide activatable constructor? */
-	    throw new ActivationException(
-		"activation constructor not defined", e);
-	} catch (NoSuchMethodError e) {
-	    /* code recompiled and user forgot to provide
-	     *  activatable constructor?
-	     */
-	    throw new ActivationException(
-		"activation constructor not defined", e);
-	} catch (InvocationTargetException e) {
-	    throw new ActivationException("exception constructing object",
-					  e.getTargetException());
-	} catch (ActivationException e) {
-	    throw e;
-	} catch (Exception e) {
-	    throw new ActivationException("unable to activate object", e);
-	} finally {
-	    releaseLock(id);
-	    checkInactiveGroup();
-	}
-    }
-
-    /**
-     * Attempts to make the remote object that is associated with the
-     * specified activation identifier, and that was exported as a JRMP
-     * {@link java.rmi.activation.Activatable} object, inactive. This method
-     * calls <code>Activatable.unexportObject</code> with the active remote
-     * object and <code>false</code>, to unexport the object. If that call
-     * returns <code>false</code>, this method returns <code>false</code>.
-     * If that call returns <code>true</code>, the object is marked inactive
-     * in this virtual machine, the superclass <code>inactiveObject</code>
-     * method is called with the same activation identifier, with the
-     * <code>ActivationMonitor</code> constraints (if any) set as
-     * contextual client constraints, and with the group's subject (if any)
-     * set as the executing subject, and this method returns <code>true</code>.
-     *
-     * @param id the activation identifier
-     * @return <code>true</code> if the object was successfully made
-     * inactive; <code>false</code> otherwise
-     * @throws UnknownObjectException if the object is not known to be
-     * active (it may already be inactive)
-     * @throws ActivationException if an activation error occurs
-     * @throws InactiveGroupException if the group is inactive
-     * @throws RemoteException if the remote call to the activation
-     * monitor fails
-     *
-     * @throws SecurityException if a security manager exists and invoking
-     * its {@link SecurityManager#checkPermission checkPermission} method
-     * with the permission <code>{@link MonitorPermission}("java.rmi.activation.ActivationMonitor.inactiveObject")</code>
-     * throws a <code>SecurityException</code> 
-     **/
-    public boolean inactiveObject(final ActivationID id)
-	throws ActivationException, RemoteException
-    {
-	SecurityManager security = System.getSecurityManager();
-	if (security != null) {
-	    security.checkPermission(inactiveObjectPermission);
-	}
-	acquireLock(id);
-	try {
-	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
-		if (state != ACTIVE) {
-		    throw new InactiveGroupException("group not active");
-		}
-		entry = (ActiveEntry) active.get(id);
-	    }
-	    if (entry == null) {
-		// REMIND: should this be silent?
-		throw new UnknownObjectException("object not active");
-	    }
-
-	    try {
-		if (!Activatable.unexportObject(entry.impl, false)) {
-		    return false;
-		}
-	    } catch (NoSuchObjectException allowUnexportedObjects) {
-	    }
-
-	    try {
-		doAction(new PrivilegedExceptionAction() {
-		    public Object run() throws Exception {
-			monitor.inactiveObject(id);
-			return null;
-		    }
-		});
-	    } catch (UnknownObjectException allowUnregisteredObjects) {
-	    }
-
-	    synchronized (ActivationGroupImpl.class) {
-		active.remove(id);
-	    }
-	} finally {
-	    releaseLock(id);
-	    checkInactiveGroup();
-	}
-
-	return true;
-    }
-
-    /**
-     * Attempts to make the remote object that is associated with the
-     * specified activation identifier, and that was exported through the
-     * specified exporter, inactive. The {@link Exporter#unexport unexport}
-     * method of the specified exporter is called with <code>false</code>
-     * as an argument. If that call returns <code>false</code>, this method
-     * returns <code>false</code>. If that call returns <code>true</code>,
-     * the object is marked inactive in this virtual machine, the
-     * superclass <code>inactiveObject</code> method is called with the
-     * activation identifier, with the <code>ActivationMonitor</code>
-     * constraints (if any) set as contextual client constraints, and with
-     * the group's subject (if any) set as the executing subject, and this
-     * method returns <code>true</code>.
-     *
-     * @param id the activation identifier
-     * @param exporter the exporter to use to unexport the object
-     * @return <code>true</code> if the object was successfully made
-     * inactive; <code>false</code> otherwise
-     * @throws UnknownObjectException if the object is not known to be
-     * active (it may already be inactive)
-     * @throws ActivationException if an activation error occurs
-     * @throws InactiveGroupException if the group is inactive
-     * @throws RemoteException if the remote call to the activation monitor
-     * fails
-     * @throws SecurityException if a security manager exists and invoking
-     * its {@link SecurityManager#checkPermission checkPermission} method
-     * with the permission <code>{@link MonitorPermission}("java.rmi.activation.ActivationMonitor.inactiveObject")</code>
-     * throws a <code>SecurityException</code> 
-     **/
-    public boolean inactiveObject(final ActivationID id, Exporter exporter)
-	throws ActivationException, RemoteException
-    {
-	SecurityManager security = System.getSecurityManager();
-	if (security != null) {
-	    security.checkPermission(inactiveObjectPermission);
-	}
-	acquireLock(id);
-	try {
-	    ActiveEntry entry;
-	    synchronized (ActivationGroupImpl.class) {
-		if (state != ACTIVE) {
-		    throw new InactiveGroupException("group not active");
-		}
-		entry = (ActiveEntry) active.get(id);
-	    }
-	    if (entry == null) {
-		// REMIND: should this be silent?
-		throw new UnknownObjectException("object not active");
-	    }
-
-	    if (!exporter.unexport(false)) {
-		return false;
-	    }
-
-	    try {
-		doAction(new PrivilegedExceptionAction() {
-		    public Object run() throws Exception {
-			monitor.inactiveObject(id);
-			return null;
-		    }
-		});
-	    } catch (UnknownObjectException allowUnregisteredObjects) {
-	    }
-
-	    synchronized (ActivationGroupImpl.class) {
-		active.remove(id);
-	    }
-	} finally {
-	    releaseLock(id);
-	    checkInactiveGroup();
-	}
-
-	return true;
-    }
-
-    /*
-     * Determines if the group has become inactive and if so,
-     * marks it as such, notifies the daemon, and unexports the group.
-     */
-    private static void checkInactiveGroup() {
-	synchronized (ActivationGroupImpl.class) {
-	    if (state == ACTIVE) {
-		if (!active.isEmpty() || !lockedIDs.isEmpty()) {
-		    return;
-		}
-		state = INACTIVE;
-	    } else if (state == INACTIVE) {
-		return;
-	    } else if (state == CREATED) {
-		state = UNUSED;
-	    } else {
-		if (login != null) {
-		    try {
-			login.logout();
-		    } catch (LoginException e) {
-		    }
-		    login = null;
-		}
-		state = UNUSED;
-		return;
-	    }
-	}
-	try {
-	    doAction(new PrivilegedExceptionAction() {
-		public Object run() throws Exception {
-		    monitor.inactiveGroup(groupID, incarnation);
-		    return null;
-		}
-	    });
-	} catch (Exception ignoreDeactivateFailure) {
-	}
-	Runnable action = new Runnable() {
-	    public void run() {
-		long stop = System.currentTimeMillis() + unexportTimeout;
-		// allow a failing newInstance call to finish first
-		boolean force = false;
-		while (!exporter.unexport(force)) {
-		    long rem = stop - System.currentTimeMillis();
-		    if (rem <= 0) {
-			force = true;
-		    } else {
-			try {
-			    Thread.sleep(Math.min(rem, unexportWait));
-			} catch (InterruptedException e) {
-			}
-		    }
-		}
-		if (login != null) {
-		    try {
-			login.logout();
-		    } catch (LoginException e) {
-		    }
-		}
-	    }
-	};
-	if (state == UNUSED) {
-	    action.run();
-	} else {
-	    Executor systemThreadPool =
-		(Executor) AccessController.doPrivileged(
-		    (login == null) ?
-		    (PrivilegedAction) new GetThreadPoolAction(false) :
-		    new PrivilegedAction() {
-			public Object run() {
-			    return Subject.doAsPrivileged(
-					      login.getSubject(),
-					      new GetThreadPoolAction(false),
-					      null);
-			}
-		});
-	    systemThreadPool.execute(action, "UnexportGroup");
-	}
-    }
-
-    /**
-     * Marks the object as active in this virtual machine, and calls the
-     * superclass <code>activeObject</code> method with the same arguments,
-     * with the <code>ActivationMonitor</code> constraints (if any) set as
-     * contextual client constraints, and with the group's subject (if any)
-     * set as the executing subject. Any <code>RemoteException</code>
-     * thrown by this call is caught and ignored. If the object is already
-     * marked as active in this virtual machine, this method simply
-     * returns.
-     *
-     * @param id the activation identifier
-     * @param impl the active remote object
-     * @throws UnknownObjectException if no object is registered under
-     * the specified activation identifier
-     * @throws ActivationException if an activation error occurs
-     * @throws InactiveGroupException if the group is inactive
-     * @throws SecurityException if a security manager exists and invoking
-     * its {@link SecurityManager#checkPermission checkPermission} method
-     * with the permission <code>{@link MonitorPermission}("java.rmi.activation.ActivationMonitor.activeObject")</code>
-     * throws a <code>SecurityException</code> 
-     **/
-    public void activeObject(final ActivationID id, Remote impl)
-	throws ActivationException
-    {
-	SecurityManager security = System.getSecurityManager();
-	if (security != null) {
-	    security.checkPermission(activeObjectPermission);
-	}
-	final ActiveEntry entry = new ActiveEntry(impl);
-	acquireLock(id);
-	try {
-	    synchronized (ActivationGroupImpl.class) {
-		if (state != ACTIVE) {
-		    throw new InactiveGroupException("group not active");
-		}
-		if (active.containsKey(id)) {
-		    return;
-		}
-		active.put(id, entry);
-	    }
-	    // created new entry, so inform monitor of active object
-	    try {
-		doAction(new PrivilegedExceptionAction() {
-		    public Object run() throws Exception {
-			monitor.activeObject(id, entry.mobj);
-			return null;
-		    }
-		});
-	    } catch (RemoteException ignore) {
-		// daemon can still find it by calling newInstance
-	    }
-	} finally {
-	    releaseLock(id);
-	    checkInactiveGroup();
-	}
-    }
-
-    /**
-     * Execute the specified action on behalf of the server subject without
-     * requiring the caller to have doAsPrivileged permission.
-     */
-    private static Object doAction(final PrivilegedExceptionAction action)
-	throws ActivationException, RemoteException
-    {
-	try {
-	    if (login == null) {
-		return AccessController.doPrivileged(action);
-	    } else {
-		return AccessController.doPrivileged(
-		    new PrivilegedExceptionAction() {
-		        public Object run() throws Exception {
-			    try {
-				return Subject.doAsPrivileged(
-					   login.getSubject(), action, null);
-			    } catch (PrivilegedActionException e) {
-				throw e.getException();
-			    }
-			}
-		});
-	    }
-	} catch (PrivilegedActionException e) {
-	    Exception ex = e.getException();
-	    if (ex instanceof RemoteException) {
-		throw (RemoteException) ex;
-	    } else if (ex instanceof ActivationException) {
-		throw (ActivationException) ex;
-	    } else {
-		throw new ActivationException("unexpected failure", ex);
-	    }
-	}
-    }
-
-    /**
-     * Entry in table for active object.
-     */
-    private static class ActiveEntry {
-	Remote impl;
-	MarshalledObject mobj;
-
-	ActiveEntry(Remote impl) throws ActivationException {
-	    this.impl = impl;
-	    try {
-		Object proxy ;
-		if (impl instanceof ProxyAccessor) {
-		    proxy = ((ProxyAccessor) impl).getProxy();
-		    if (proxy == null) {
-			throw new ActivationException(
-			    "ProxyAccessor.getProxy returned null");
-		    }
-		} else {
-		    proxy = impl;
-		}
-		this.mobj = new MarshalledObject(proxy);
-	    } catch (IOException e) {
-		throw new ActivationException(
-		    "failed to marshal remote object", e);
-	    }
-	}
-    }
-}
+/*
+ * 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.phoenix;
+
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationGroupDesc;
+import java.rmi.activation.ActivationGroupID;
+
+/**
+ * The default activation group implementation for phoenix.  Instances of
+ * this class are configurable through a {@link Configuration}, as detailed
+ * further below, and provide the necessary support to allow exporter-based
+ * remote objects to go inactive.  Instances of this class support the
+ * creation of remote objects through the normal activatable constructor;
+ * an activatable remote object must either implement the {@link
+ * ProxyAccessor} interface to return a suitable proxy for the remote
+ * object, or the remote object must itself be serializable and marshalling
+ * the object must produce a suitable proxy for the remote object.
+ * 
+ * <p>An instance of this class can be configured by specifying an
+ * {@link ActivationGroupData} instance containing configuration options
+ * as the initialization data for the activation group. Typically
+ * this is accomplished indirectly, by setting the
+ * <code>groupConfig</code> configuration entry for
+ * phoenix itself. The following entries are obtained from the configuration,
+ * all for the component named <code>com.sun.jini.phoenix</code>:
+ *
+ *  <table summary="Describes the loginContext configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      loginContext</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>{@link javax.security.auth.login.LoginContext}</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>null</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> JAAS login context
+ *  </table>
+ *
+ *  <table summary="Describes the inheritGroupSubject configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      inheritGroupSubject</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>boolean</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>false</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> if <code>true</code>, group subject is inherited
+ *		when an activatable object is created 
+ *  </table>
+ *
+ *  <table summary="Describes the instantiatorExporter configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      instantiatorExporter</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>{@link net.jini.export.Exporter}</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> retains existing JRMP export of instantiator
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> {@link java.rmi.activation.ActivationInstantiator}
+ *		exporter
+ *  </table>
+ *
+ *  <table summary="Describes the monitorPreparer configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      monitorPreparer</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>{@link net.jini.security.ProxyPreparer}</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>new {@link
+ *		net.jini.security.BasicProxyPreparer}()</code> 
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> {@link java.rmi.activation.ActivationMonitor}
+ *		proxy preparer 
+ *  </table>
+ *
+ *  <table summary="Describes the systemPreparer configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      systemPreparer</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>{@link net.jini.security.ProxyPreparer}</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>new {@link
+ *		net.jini.security.BasicProxyPreparer}()</code> 
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> {@link java.rmi.activation.ActivationSystem}
+ *		proxy preparer 
+ *  </table>
+ *
+ *  <table summary="Describes the unexportTimeout configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      unexportTimeout</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>int</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>60000</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> maximum time in milliseconds to wait for
+ *		in-progress calls to finish before forcibly unexporting the
+ *		group when going inactive 
+ *  </table>
+ *
+ *  <table summary="Describes the unexportWait configuration entry"
+ *         border="0" cellpadding="2">
+ *    <tr valign="top">
+ *      <th scope="col" summary="layout"> <font size="+1">&#X2022;</font>
+ *      <th scope="col" align="left" colspan="2"> <font size="+1"><code>
+ *      unexportWait</code></font>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Type: <td> <code>int</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Default: <td> <code>10</code>
+ *    <tr valign="top"> <td> &nbsp <th scope="row" align="right">
+ *      Description: <td> milliseconds to wait between unexport attempts
+ *		when going inactive 
+ *  </table>
+ * 
+ * <p>This class depends on its {@link #createGroup createGroup} method being
+ * called to initialize the activation group. As such, this class cannot be
+ * used in conjunction with the standard <code>rmid</code>.
+ *
+ * @author Sun Microsystems, Inc.
+ * 
+ * @since 2.0
+ **/
+public class ActivationGroupImpl extends AbstractActivationGroup {
+   
+    /**
+     * Creates an {@link java.rmi.activation.ActivationGroup} instance and
+     * returns it. An {@link ActivationGroupData} instance is extracted from
+     * the initialization data, and a {@link Configuration} is obtained by
+     * calling
+     * {@link net.jini.config.ConfigurationProvider#getInstance
+     * Configuration.Provider.getInstance} with the configuration options from
+     * that instance. A {@link LoginContext} is obtained from the
+     * <code>loginContext</code> configuration entry, if one exists; if the
+     * value is not <code>null</code>, a login is performed on that context,
+     * and the resulting {@link Subject} (set to be read-only) is used as the
+     * subject when executing the rest of this method. The subject is also
+     * used for all subsequent remote calls by this class to the
+     * {@link ActivationMonitor}. The {@link ActivationSystem} proxy
+     * (obtained from the <code>ActivationGroupID</code>) is passed to the
+     * {@link ProxyPreparer} given by the <code>systemPreparer</code>
+     * configuration entry, if one exists; a new
+     * <code>ActivationGroupID</code> is constructed with the resulting proxy.
+     * An {@link Exporter} instance is obtained from the
+     * <code>instantiatorExporter</code> configuration entry, if one exists;
+     * this exporter will be used (in the constructor of this class) to export
+     * the group. A <code>ProxyPreparer</code> instance is obtained from the
+     * <code>monitorPreparer</code> configuration entry, if one exists; this
+     * preparer will be used (in the constructor of this class) to prepare the
+     * <code>ActivationMonitor</code>. A call is then made to
+     * {@link ActivationGroup#createGroup ActivationGroup.createGroup} with
+     * the new group identifier, the activation group descriptor, and the
+     * group incarnation number, and the result of that call is returned.
+     *
+     * @param id the activation group identifier
+     * @param desc the activation group descriptor
+     * @param incarnation the group's incarnation number (zero on initial
+     * creation)
+     * @return the created activation group
+     * @throws ActivationException if a group already exists or if an
+     * exception occurs during group creation
+     */
+    public static synchronized
+	java.rmi.activation.ActivationGroup createGroup(
+					      final ActivationGroupID id,
+					      final ActivationGroupDesc desc,
+					      final long incarnation)
+        throws ActivationException
+    {
+        return AbstractActivationGroup.createGroup(id, desc, incarnation);
+    }
+      
+    /**
+     * Creates an instance with the specified group identifier and
+     * initialization data. This constructor must be called indirectly,
+     * via {@link #createGroup createGroup}. By default, this instance
+     * automatically exports itself as a {@link UnicastRemoteObject}. (This
+     * is a limitation of the existing activation system design.) If an
+     * {@link Exporter} was obtained by {@link #createGroup createGroup},
+     * then this instance is unexported from the JRMP runtime and re-exported
+     * using that exporter. (Any incoming remote calls received on the
+     * original JRMP export before this instance can be unexported will be
+     * refused with a security exception thrown.) The
+     * {@link ActivationSystem#activeGroup activeGroup} method of the
+     * activation system proxy (in the group identifier) is called to
+     * make the group active. The returned {@link ActivationMonitor} proxy
+     * is passed to the corresponding {@link ProxyPreparer} obtained by
+     * <code>createGroup</code>. Note that after this constructor returns,
+     * {@link ActivationGroup#createGroup ActivationGroup.createGroup} will
+     * also call <code>activeGroup</code> (so the activation system must
+     * accept idempotent calls to that method), but the
+     * <code>ActivationMonitor</code> proxy returned by that call will not be
+     * used.
+     * 
+     * @param id the activation group identifier
+     * @param data group initialization data (ignored)
+     * @throws RemoteException if the group could not be exported or
+     * made active, or proxy preparation fails
+     * @throws ActivationException if the constructor was not called
+     * indirectly from <code>createGroup</code>
+     */
+    public ActivationGroupImpl(ActivationGroupID id, MarshalledObject data)
+	throws ActivationException, RemoteException
+    {
+	super(id, data);
+        export();
+    }
+    
+}