You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2012/01/21 08:28:36 UTC

svn commit: r1234278 [18/29] - in /river/tck: ./ configs/ doc/ doc/api/ doc/api/com/ doc/api/com/sun/ doc/api/com/sun/jini/ doc/api/com/sun/jini/compat/ doc/api/com/sun/jini/compat/admin1/ doc/api/com/sun/jini/compat/admin2/ doc/api/com/sun/jini/compat...

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

Added: river/tck/src/com/sun/jini/compat/reggie/RegistrarLease.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/RegistrarLease.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/RegistrarLease.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/RegistrarLease.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,85 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import net.jini.core.lease.*;
+
+/**
+ * The base class for lease proxies.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+abstract class RegistrarLease extends com.sun.jini.lease.AbstractLease {
+
+    private static final long serialVersionUID = 1286538697644640310L;
+
+    /**
+     * The registrar.
+     *
+     * @serial
+     */
+    protected final Registrar server;
+    /**
+     * The internal lease id.
+     *
+     * @serial
+     */
+    protected final long leaseID;
+
+    /** Simple constructor. */
+    protected RegistrarLease(Registrar server, long leaseID, long expiration) {
+	super(expiration);
+	this.server = server;
+	this.leaseID = leaseID;
+    }
+
+    /** Create a lease map. */
+    public LeaseMap createLeaseMap(long duration) {
+	return new RegistrarLeaseMap(this, duration);
+    }
+
+    /**
+     * Two leases can be batched if they are both RegistrarLeases and
+     * have the same server.
+     */
+    public boolean canBatch(Lease lease) {
+	return (lease instanceof RegistrarLease &&
+		server.equals(((RegistrarLease)lease).server));
+    }
+
+    /** Return the registrar. */
+    Registrar getRegistrar() {
+	return server;
+    }
+
+    /** Returns the lease ID */
+    long getLeaseID() {
+	return leaseID;
+    }
+
+    /** Returns the service ID, or the event ID as a Long */
+    abstract Object getRegID();
+
+    /** Set the expiration. */
+    void setExpiration(long expiration) {
+	this.expiration = expiration;
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/RegistrarLeaseMap.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/RegistrarLeaseMap.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/RegistrarLeaseMap.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/RegistrarLeaseMap.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,123 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import net.jini.core.lease.*;
+import net.jini.core.lookup.ServiceID;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+
+/**
+ * The LeaseMap implementation class for registrar leases.  Clients only see
+ * instances via the LeaseMap interface.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class RegistrarLeaseMap extends com.sun.jini.lease.AbstractLeaseMap {
+
+    private static final long serialVersionUID = 1840099461579576431L;
+
+    /**
+     * The registrar
+     *
+     * @serial
+     */
+    private final Registrar server;
+
+    /** Simple constructor */
+    public RegistrarLeaseMap(RegistrarLease lease, long duration) {
+	super(lease, duration);
+	this.server = lease.getRegistrar();
+    }
+
+    /** Any RegistrarLease from the same server can be in the map */
+    public boolean canContainKey(Object key) {
+	return (key instanceof RegistrarLease &&
+		server.equals(((RegistrarLease)key).getRegistrar()));
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public void renewAll() throws LeaseMapException, RemoteException {
+	int size = map.size();
+	if (size == 0)
+	    return;
+	Object[] regIDs = new Object[size];
+	long[] leaseIDs = new long[size];
+	long[] durations = new long[size];
+	int i = 0;
+	for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); i++) {
+	    Map.Entry e = (Map.Entry)iter.next();
+	    RegistrarLease ls = (RegistrarLease)e.getKey();
+	    regIDs[i] = ls.getRegID();
+	    leaseIDs[i] = ls.getLeaseID();
+	    durations[i] = ((Long)e.getValue()).longValue();
+	}
+	RenewResults results = server.renewLeases(regIDs, leaseIDs, durations);
+	long now = System.currentTimeMillis();
+	HashMap emap = (results.exceptions != null) ?
+	    	       new HashMap(2 * results.exceptions.length + 1) : null;
+	i = 0;
+	int j = 0;
+	for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); i++) {
+	    Map.Entry e = (Map.Entry)iter.next();
+	    long duration = results.durations[i];
+	    if (duration >= 0) {
+		((RegistrarLease)e.getKey()).setExpiration(duration + now);
+	    } else {
+		emap.put(e.getKey(), results.exceptions[j++]);
+		iter.remove();
+	    }
+	}
+	if (emap != null)
+	    throw new LeaseMapException("lease renewal failures", emap);
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public void cancelAll() throws LeaseMapException, RemoteException {
+	int size = map.size();
+	if (size == 0)
+	    return;
+	Object[] regIDs = new Object[size];
+	long[] leaseIDs = new long[size];
+	int i = 0;
+	for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
+	    RegistrarLease ls = (RegistrarLease)iter.next();
+	    regIDs[i] = ls.getRegID();
+	    leaseIDs[i] = ls.getLeaseID();
+	}
+	Exception[] exceptions = server.cancelLeases(regIDs, leaseIDs);
+	if (exceptions == null)
+	    return;
+	i = 0;
+	HashMap emap = new HashMap(13);
+	for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
+	    RegistrarLease ls = (RegistrarLease)iter.next();
+	    Exception ex = exceptions[i];
+	    if (ex != null) {
+		emap.put(ls, ex);
+		iter.remove();
+	    }
+	}
+	throw new LeaseMapException("lease cancellation failures", emap);
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/RegistrarProxy.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/RegistrarProxy.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/RegistrarProxy.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/RegistrarProxy.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,198 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import net.jini.core.lookup.*;
+import net.jini.core.event.*;
+import net.jini.admin.Administrable;
+import net.jini.core.discovery.LookupLocator;
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.rmi.UnmarshalException;
+import java.rmi.MarshalledObject;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * A RegistrarProxy is a proxy for a registrar.  Clients only see instances
+ * via the ServiceRegistrar interface (and the RegistrarAdmin interface
+ * if they need it).
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class RegistrarProxy implements ServiceRegistrar, Administrable,
+                                java.io.Serializable
+{
+    private static final long serialVersionUID = 2425188657680236255L;
+
+    /**
+     * The registrar
+     *
+     * @serial
+     */
+    private final Registrar server;
+    /**
+     * The registrar's service ID
+     *
+     * @serial
+     */
+    private final ServiceID serviceID;
+
+    /** Simple constructor. */
+    public RegistrarProxy(Registrar server, ServiceID serviceID) {
+	this.server = server;
+	this.serviceID = serviceID;
+    }
+
+    public Object getAdmin() throws RemoteException {
+        return server.getAdmin();
+    }
+
+    public ServiceRegistration register(ServiceItem item, long leaseDuration)
+	throws RemoteException
+    {
+	return server.register(new Item(item), leaseDuration);
+    }
+
+    public Object lookup(ServiceTemplate tmpl) throws RemoteException {
+	MarshalledObject obj = server.lookup(new Template(tmpl));
+	if (obj == null)
+	    return null;
+	try {
+	    return obj.get();
+	} catch (IOException e) {
+	    throw new UnmarshalException("error unmarshalling return", e);
+	} catch (ClassNotFoundException e) {
+	    throw new UnmarshalException("error unmarshalling return", e);
+	}
+    }
+
+    public ServiceMatches lookup(ServiceTemplate tmpl, int maxMatches)
+	throws RemoteException
+    {
+	return server.lookup(new Template(tmpl), maxMatches).get();
+    }
+
+    public EventRegistration notify(ServiceTemplate tmpl,
+				    int transitions,
+				    RemoteEventListener listener,
+				    MarshalledObject handback,
+				    long leaseDuration)
+	throws RemoteException
+    {
+	return server.notify(new Template(tmpl), transitions, listener,
+			     handback, leaseDuration);
+    }
+
+    public Class[] getEntryClasses(ServiceTemplate tmpl)
+	throws RemoteException
+    {
+	return EntryClassBase.toClass(
+				  server.getEntryClasses(new Template(tmpl)));
+    }
+
+    public Object[] getFieldValues(ServiceTemplate tmpl,
+				   int setIndex, String field)
+	throws NoSuchFieldException, RemoteException
+    {
+	/* check that setIndex and field are valid, convert field to index */
+	ClassMapper.EntryField[] efields =
+	    ClassMapper.getFields(
+			     tmpl.attributeSetTemplates[setIndex].getClass());
+	int fidx;
+	for (fidx = efields.length; --fidx >= 0; ) {
+	    if (field.equals(efields[fidx].field.getName()))
+		break;
+	}
+	if (fidx < 0)
+	    throw new NoSuchFieldException(field);
+	Object[] values = server.getFieldValues(new Template(tmpl),
+						setIndex, fidx);
+	/* unmarshal each value, replacing with null on exception */
+	if (values != null && efields[fidx].marshal) {
+	    for (int i = values.length; --i >= 0; ) {
+		try {
+		    values[i] = ((MarshalledObject)values[i]).get();
+		    continue;
+		} catch (Throwable e) {
+		    handleException(e);
+		}
+		values[i] = null;
+	    }
+	}
+	return values;
+    }
+
+    /**
+     * Rethrow the exception if it is an Error, unless it is a LinkageError,
+     * OutOfMemoryError, or StackOverflowError.  Otherwise print the
+     * exception stack trace if debugging is enabled.
+     */
+    static void handleException(final Throwable e) {
+	if (e instanceof Error &&
+	    !(e instanceof LinkageError ||
+	      e instanceof OutOfMemoryError ||
+	      e instanceof StackOverflowError))
+	    throw (Error)e;
+	AccessController.doPrivileged(new PrivilegedAction() {
+	    public Object run() {
+		try {
+		    if (System.getProperty("com.sun.jini.compat.reggie.proxy.debug")
+			!= null)
+			e.printStackTrace();
+		} catch (SecurityException ee) {
+		}
+		return null;
+	    }
+	});
+    }
+
+    public Class[] getServiceTypes(ServiceTemplate tmpl, String prefix)
+	throws RemoteException
+    {
+	return ServiceTypeBase.toClass(
+				   server.getServiceTypes(new Template(tmpl),
+							  prefix));
+    }
+
+    public ServiceID getServiceID() {
+	return serviceID;
+    }
+
+    public LookupLocator getLocator() throws RemoteException {
+	return server.getLocator();
+    }
+
+    public String[] getGroups() throws RemoteException {
+	return server.getMemberGroups();
+    }
+
+    public int hashCode() {
+	return serviceID.hashCode();
+    }
+
+    /** Proxies for servers with the same serviceID are considered equal. */
+    public boolean equals(Object obj) {
+	return (obj instanceof RegistrarProxy &&
+		serviceID.equals(((RegistrarProxy)obj).serviceID));
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/Registration.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/Registration.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/Registration.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/Registration.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,93 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import java.rmi.RemoteException;
+import net.jini.core.entry.Entry;
+import net.jini.core.lookup.*;
+import net.jini.core.lease.*;
+
+/**
+ * Implementation class for the ServiceRegistration interface.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class Registration implements ServiceRegistration, java.io.Serializable
+{
+    private static final long serialVersionUID = -276552004282140614L;
+
+    /**
+     * The registrar
+     *
+     * @serial
+     */
+    private final Registrar server;
+    /**
+     * The service lease
+     *
+     * @serial
+     */
+    private final ServiceLease lease;
+
+    /** Simple constructor */
+    public Registration(Registrar server, ServiceLease lease) {
+	this.server = server;
+	this.lease = lease;
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public ServiceID getServiceID() {
+	return lease.getServiceID();
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public Lease getLease() {
+	return lease;
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public void addAttributes(Entry[] attrSets)
+	throws UnknownLeaseException, RemoteException
+    {
+	server.addAttributes(lease.getServiceID(),
+			     lease.getLeaseID(),
+			     EntryRep.toEntryRep(attrSets, true));
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public void modifyAttributes(Entry[] attrSetTmpls, Entry[] attrSets)
+	throws UnknownLeaseException, RemoteException
+    {
+	server.modifyAttributes(lease.getServiceID(),
+				lease.getLeaseID(),
+				EntryRep.toEntryRep(attrSetTmpls, false),
+				EntryRep.toEntryRep(attrSets, false));
+    }
+
+    // This method's javadoc is inherited from an interface of this class
+    public void setAttributes(Entry[] attrSets)
+	throws UnknownLeaseException, RemoteException
+    {
+	server.setAttributes(lease.getServiceID(),
+			     lease.getLeaseID(),
+			     EntryRep.toEntryRep(attrSets, true));
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/RenewResults.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/RenewResults.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/RenewResults.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/RenewResults.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,57 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+/*
+ * RenewResults contains the return values of a renewLeases call on the
+ * registrar.  Instances are never visible to clients, they are private
+ * to the communication between the LeaseMap proxy and the registrar.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class RenewResults implements java.io.Serializable {
+
+    private static final long serialVersionUID = -8280333780058043204L;
+
+    /**
+     * The granted duration for each lease.  The length of this array
+     * is the same as the length of the durations parameter to renewLeases,
+     * and is in the same order.  If a duration is -1, it indicates that
+     * an exception was thrown for this lease.
+     *
+     * @serial
+     */
+    public long[] durations;
+    /**
+     * Any exceptions thrown.  The length of this array is the same as
+     * the number of -1 elements in durations.  The exceptions are in
+     * order.
+     *
+     * @serial
+     */
+    public Exception[] exceptions;
+
+    /** Simple constructor */
+    public RenewResults(long[] durations, Exception[] exceptions) {
+	this.durations = durations;
+	this.exceptions = exceptions;
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/ServiceLease.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/ServiceLease.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/ServiceLease.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/ServiceLease.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,88 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import net.jini.core.lease.*;
+import net.jini.core.lookup.ServiceID;
+import java.rmi.RemoteException;
+
+/**
+ * A ServiceLease is a proxy for a service registration lease at a registrar.
+ * Clients only see instances via the Lease interface.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class ServiceLease extends RegistrarLease {
+
+    private static final long serialVersionUID = 4366637533663829830L;
+
+    /**
+     * The service id assigned at registration.
+     *
+     * @serial
+     */
+    private final ServiceID serviceID;
+
+    /** Simple constructor. */
+    ServiceLease(Registrar server,
+		 ServiceID serviceID,
+		 long leaseID,
+		 long expiration)
+    {
+	super(server, leaseID, expiration);
+	this.serviceID = serviceID;
+    }
+
+    public void cancel() throws UnknownLeaseException, RemoteException {
+	server.cancelServiceLease(serviceID, leaseID);
+    }
+
+    /** Do the actual renew. */
+    protected long doRenew(long duration)
+	throws UnknownLeaseException, RemoteException
+    {
+	return server.renewServiceLease(serviceID, leaseID, duration);
+    }
+
+    /** Returns the service ID */
+    ServiceID getServiceID() {
+	return serviceID;
+    }
+
+    Object getRegID() {
+	return serviceID;
+    }
+
+    /** Returns a hash code based on content. */
+    public int hashCode() {
+	return server.hashCode() ^ serviceID.hashCode() ^ (int)leaseID;
+    }
+
+    /** Equal if for the same serviceID and leaseID at the same registrar. */
+    public boolean equals(Object obj) {
+	if (!(obj instanceof ServiceLease))
+	    return false;
+	ServiceLease ls = (ServiceLease)obj;
+	return (server.equals(ls.server) &&
+		serviceID.equals(ls.serviceID) &&
+		leaseID == ls.leaseID);
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/ServiceType.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/ServiceType.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/ServiceType.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/ServiceType.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,291 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.server.RMIClassLoader;
+import java.util.StringTokenizer;
+
+/**
+ * A ServiceType is a descriptor for a class, packaged up for
+ * transmission between client-side proxies and the registrar server.
+ * Instances are never visible to clients, they are private to the
+ * communication between the proxies and the server.
+ * <p>
+ * This class only has a bare minimum of methods, to minimize
+ * the amount of code downloaded into clients.
+ * The implementation is complicated by a requirement to support classes
+ * generated by java.lang.reflect.Proxy with a single source that will
+ * compile and run against J2SE(TM) versions 1.2.x, 1.3.x, and 1.4.x.
+ * <p>
+ * Equality is based on object identity, on the assumption that
+ * ClassResolver is always used and that equality is only interesting
+ * in the registrar.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ * @see ClassMapper
+ * @see ClassResolver
+ */
+class ServiceType implements java.io.Serializable {
+
+    /**
+     * Class name. If the class is generated by java.lang.reflect.Proxy,
+     * then the name is of the form ";iface1;iface2;...;ifaceN".
+     *
+     * @serial
+     */
+    protected String name;
+    /**
+     * Descriptor for the superclass.
+     *
+     * @serial
+     */
+    protected ServiceType superclass;
+    /**
+     * Descriptor for the interfaces.  As a special case, interfaces is
+     * null for the descriptor for java.lang.Object, and non-null otherwise.
+     * This avoids carrying a boolean isInterface around.
+     *
+     * @serial
+     */
+    protected ServiceType[] interfaces;
+    /**
+     * An instance containing only name, no supertype info.
+     * This is only used on the registrar side, to minimize the amount
+     * of info transmitted back to clients.
+     */
+    protected transient ServiceType replacement;
+    /** The concrete classes. */
+    protected transient ServiceType[] concreteClasses;
+
+    private static final long serialVersionUID = 9194732528513491231L;
+    private static final ServiceType[] empty = {};
+    /** Proxy.isProxyClass, if it exists (1.3 and later) */
+    private static Method isProxyClass;
+    /** Proxy.getProxyClass, if it exists (1.3 and later) */
+    private static Method getProxyClass;
+    /** RMIClassLoader.getClassLoader, if it exists (1.3 and later) */
+    private static Method getClassLoader;
+    /** RMIClassLoader.loadProxyClass, if it exists (1.4 and later) */
+    private static Method loadProxyClass;
+
+    static {
+	try {
+	    Class c = Class.forName("java.lang.reflect.Proxy");
+	    isProxyClass = c.getMethod("isProxyClass",
+				       new Class[]{Class.class});
+	    getProxyClass = c.getMethod("getProxyClass",
+					new Class[]{ClassLoader.class,
+						    Class[].class});
+	} catch (ClassNotFoundException e) {
+	} catch (NoSuchMethodException e) {
+	    throw new InternalError(e.toString());
+	}
+	try {
+	    getClassLoader = RMIClassLoader.class.getMethod(
+				  "getClassLoader", new Class[]{String.class});
+	    loadProxyClass = RMIClassLoader.class.getMethod(
+				  "loadProxyClass",
+				  new Class[]{String.class, String[].class,
+					      ClassLoader.class});
+	} catch (NoSuchMethodException e) {
+	}
+    }
+
+    /** Should only be called by ClassMapper */
+    public ServiceType(Class clazz,
+		       ServiceType superclass,
+		       ServiceType[] interfaces)
+    {
+	try {
+	    if (isProxyClass == null ||
+		!((Boolean) isProxyClass.invoke(
+				  null, new Object[]{clazz})).booleanValue())
+	    {
+		name = clazz.getName();
+	    } else if (interfaces.length == 0) {
+		name = ";";
+	    } else {
+		StringBuffer buf = new StringBuffer();
+		for (int i = 0; i < interfaces.length; i++) {
+		    buf.append(';');
+		    buf.append(interfaces[i].getName());
+		}
+		name = buf.toString();
+	    }
+	} catch (IllegalAccessException e) {
+	    throw new InternalError(e.toString());
+	} catch (InvocationTargetException e) {
+	    Throwable t = e.getTargetException();
+	    if (t instanceof RuntimeException)
+		throw (RuntimeException) t;
+	    if (t instanceof Error)
+		throw (Error) t;
+	    throw new InternalError(t.toString());
+	}
+	this.superclass = superclass;
+	if (clazz != Object.class)
+	    this.interfaces = interfaces;
+    }
+
+    /**
+     * Constructor used for creating replacement instances,
+     * containing only name.
+     */
+    private ServiceType(ServiceType stype) {
+	name = stype.name;
+    }
+
+    /** Return the class name */
+    public String getName() {
+	return name;
+    }
+
+    /** Return the superclass descriptor */
+    public ServiceType getSuperclass() {
+	return superclass;
+    }
+
+    /** Return the interfaces.  The array is not a copy; do not modify it. */
+    public ServiceType[] getInterfaces() {
+	if (interfaces != null)
+	    return interfaces;
+	return empty;
+    }
+
+    /** Return the replacement, if any, containing only name and rep. */
+    public ServiceType getReplacement() {
+	return replacement;
+    }
+
+    /**
+     * This is really only needed in the registrar, but it's very
+     * convenient to have here.
+     * @see Class#isAssignableFrom
+     */
+    public boolean isAssignableFrom(ServiceType cls) {
+	if (this == cls)
+	    return true;
+	if (isInterface()) {
+	    if (isAssignableFrom(cls.interfaces))
+		return true;
+	    for (ServiceType sup = cls.superclass;
+		 sup != null && sup.interfaces != null;
+		 sup = sup.superclass)
+	    {
+		if (isAssignableFrom(sup.interfaces))
+		    return true;
+	    }
+	} else {
+	    for (ServiceType sup = cls.superclass;
+		 sup != null;
+		 sup = sup.superclass)
+	    {
+		if (this == sup)
+		    return true;
+	    }
+	}
+	return false;
+    }
+
+    /** Test if this isAssignableFrom any of the given interface types. */
+    private boolean isAssignableFrom(ServiceType[] ifaces)
+    {
+	for (int i = ifaces.length; --i >= 0; ) {
+	    if (this == ifaces[i] || isAssignableFrom(ifaces[i].interfaces))
+		return true;
+	}
+	return false;
+    }
+
+    /** @see Class#isInterface */
+    public boolean isInterface() {
+	return (superclass == null && interfaces != null);
+    }
+
+    /** Converts the descriptor to a Class instance, loading from codebase */
+    public Class toClass(String codebase)
+	throws IOException, ClassNotFoundException
+    {
+	if (name.charAt(0) != ';')
+	    return RMIClassLoader.loadClass(codebase, name);
+	if (getProxyClass == null)
+	    throw new ClassNotFoundException("java.lang.reflect.Proxy");
+	StringTokenizer st = new StringTokenizer(name, ";");
+	try {
+	    if (loadProxyClass != null) {
+		String[] ifs = new String[st.countTokens()];
+		for (int i = 0; i < ifs.length; i++) {
+		    ifs[i] = st.nextToken();
+		}
+		return (Class) loadProxyClass.invoke(
+				   null, new Object[]{codebase, ifs, null});
+	    }
+	    ClassLoader cl = (ClassLoader) getClassLoader.invoke(
+						null, new String[]{codebase});
+	    Class[] ifs = new Class[st.countTokens()];
+	    for (int i = 0; i < ifs.length; i++) {
+		ifs[i] = Class.forName(st.nextToken(), false, cl);
+	    }
+	    return (Class) getProxyClass.invoke(null, new Object[]{cl, ifs});
+	} catch (IllegalAccessException e) {
+	    throw new InternalError(e.toString());
+	} catch (InvocationTargetException e) {
+	    Throwable t = e.getTargetException();
+	    if (t instanceof ClassNotFoundException)
+		throw (ClassNotFoundException) t;
+	    if (t instanceof IOException)
+		throw (IOException) t;
+	    throw new ClassNotFoundException(name, t);
+	}
+    }
+
+    /**
+     * Sets this descriptor to be the canonical one.  Replaces the
+     * superclass with the canonical superclass, and constructs the
+     * replacement object.
+     *
+     * This should only be called by ClassResolver.
+     */
+    public void canonical(ServiceType superclass) {
+	this.superclass = superclass;
+	replacement = new ServiceType(this);
+	concreteClasses = empty;
+    }
+
+    /**
+     * Returns the set of all ServiceTypes T such that there is at least one
+     * registered service with serviceType equal to T and for which
+     * this.isAssignableFrom(T).  This is only used on the registrar side.
+     */
+    public ServiceType[] getConcreteClasses() {
+	return concreteClasses;
+    }
+
+    /** Sets the concrete classes. */
+    public void setConcreteClasses(ServiceType[] concreteClasses) {
+	if (concreteClasses.length == 0)
+	    concreteClasses = empty;
+	this.concreteClasses = concreteClasses;
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/ServiceTypeBase.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/ServiceTypeBase.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/ServiceTypeBase.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/ServiceTypeBase.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,78 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import java.rmi.server.RMIClassLoader;
+import java.io.IOException;
+
+/**
+ * A ServiceType annotated with a codebase.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class ServiceTypeBase implements java.io.Serializable {
+    /**
+     * The ServiceType.
+     *
+     * @serial
+     */
+    public final ServiceType type;
+    /**
+     * The codebase.
+     *
+     * @serial
+     */
+    public String codebase;
+
+    private static final long serialVersionUID = -2930430739238582517L;
+
+    /** Simple constructor */
+    public ServiceTypeBase(ServiceType type, String codebase) {
+	this.type = type;
+	this.codebase = codebase;
+    }
+
+    /** Sets the codebase to the codebase of the given class. */
+    public void setCodebase(Class cls) {
+	codebase = RMIClassLoader.getClassAnnotation(cls);
+    }
+
+    /**
+     * Converts an array of ServiceTypeBase to an array of Class.  If a
+     * class cannot be loaded, it is left as null.
+     */
+    public static Class[] toClass(ServiceTypeBase[] stypes)
+    {
+	Class[] classes = null;
+	if (stypes != null) {
+	    classes = new Class[stypes.length];
+	    for (int i = stypes.length; --i >= 0; ) {
+		try {
+		    ServiceTypeBase stype = stypes[i];
+		    classes[i] = stype.type.toClass(stype.codebase);
+		} catch (Throwable e) {
+		    RegistrarProxy.handleException(e);
+		}
+	    }
+	}
+	return classes;
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/Template.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/Template.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/Template.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/Template.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,70 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import net.jini.core.lookup.*;
+import java.rmi.RemoteException;
+
+/**
+ * A Template contains the fields of a ServiceTemplate packaged up for
+ * transmission between client-side proxies and the registrar server.
+ * Instances are never visible to clients, they are private to the
+ * communication between the proxies and the server.
+ * <p>
+ * This class only has a bare minimum of methods, to minimize
+ * the amount of code downloaded into clients.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+class Template implements java.io.Serializable {
+
+    private static final long serialVersionUID = 5719167991752760177L;
+
+    /**
+     * ServiceTemplate.serviceID
+     *
+     * @serial
+     */
+    public ServiceID serviceID;
+    /**
+     * ServiceTemplate.serviceTypes converted to ServiceTypes
+     *
+     * @serial
+     */
+    public ServiceType[] serviceTypes;
+    /**
+     * ServiceTemplate.attributeSetTemplates converted to EntryReps
+     *
+     * @serial
+     */
+    public EntryRep[] attributeSetTemplates;
+
+    /**
+     * Converts a ServiceTemplate to a Template.  Any exception that results
+     * is bundled up into a MarshalException.
+     */
+    public Template(ServiceTemplate tmpl) throws RemoteException {
+	serviceID = tmpl.serviceID;
+	serviceTypes = ClassMapper.toServiceType(tmpl.serviceTypes);
+	attributeSetTemplates =
+	    EntryRep.toEntryRep(tmpl.attributeSetTemplates, false);
+    }
+}

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

Added: river/tck/src/com/sun/jini/compat/reggie/TransientLookup.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/reggie/TransientLookup.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/reggie/TransientLookup.java (added)
+++ river/tck/src/com/sun/jini/compat/reggie/TransientLookup.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,109 @@
+
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.reggie;
+
+import com.sun.jini.start.ServiceStarter;
+
+import net.jini.core.lookup.ServiceRegistrar;
+
+import java.io.IOException;
+import java.rmi.RMISecurityManager;
+import java.rmi.server.RemoteObject;
+
+/**
+ * This class contains the public methods and command line interface for
+ * creating a non-activatable, non-persistent (transient) instance of the 
+ * reggie implementation of the lookup service. This class employs the
+ * utility class <code>com.sun.jini.start.ServiceStarter</code> to start
+ * the lookup service. That utility class requires that this class
+ * define a <code>public static create</code> method which performs all
+ * functions that are specific to the lookup service, and which can be
+ * invoked by the the utility class.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ * @see com.sun.jini.start.ServiceStarter
+ */
+public class TransientLookup {
+    /** The fully-qualified path.classname of this class, which will be
+     *  passed to the <code>com.sun.jini.start.ServiceStarter</code>
+     *  utility class
+     */
+    private static String starterClass = TransientLookup.class.getName();
+    /** The name used to identify the particular resource bundle from which
+     *  usage/error message information may be retrieved for display
+     *  (helpful with internationalization)
+     */
+    private static String resourcename = "lookup";
+    /**
+     * Command line interface for starting an instance of the transient
+     * version of the lookup service
+     * <p>
+     *
+     * @param args <code>String</code> array containing the command line
+     *             arguments
+     *
+     * @see com.sun.jini.start.ServiceStarter
+     */
+    public static void main(String[] args) {
+        ServiceStarter.createTransient
+                               (args, starterClass, 
+                                System.getProperty("java.class.path"),
+                                System.getProperty("java.rmi.server.codebase"),
+                                resourcename);
+    }//end main
+
+    /**
+     * This method defines how the desired lookup service is to be started.
+     * This method will be invoked through reflection by the utility
+     * class <code>com.sun.jini.start.ServiceStarter</code>. This method
+     * performs all functions that require knowledge of, or access to,
+     * the service-specific information; information that the utility
+     * class cannot easily obtain or exploit while attempting to start
+     * the lookup service.
+     * <p>
+     * This method returns a proxy that provides client-side access to
+     * the backend server of the started lookup service.
+     *
+     * @param logDirname <code>String</code> containing the full path and
+     *                   directory name in which the state of the lookup
+     *                   service to be created will be recorded for persistence
+     * 
+     * @return an instance of the public interface to the lookup service that
+     *         is to be started by this method; that is, a proxy that provides
+     *         client-side access to the backend server of the started lookup
+     *         service
+     * 
+     * @throws java.io.IOException 
+     *
+     * @see com.sun.jini.start.ServiceStarter
+     */
+    public static ServiceRegistrar create(String logDirname)
+                                                           throws IOException
+    {
+        if(System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+        RegistrarImpl registrarImpl = new RegistrarImpl(logDirname);
+        Registrar serverStub = (Registrar)RemoteObject.toStub(registrarImpl);
+	return new RegistrarProxy(serverStub,serverStub.getServiceID());
+    }//end create
+
+}//end class TransientLookup

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

Added: river/tck/src/com/sun/jini/compat/start/ActivateWrapper.java
URL: http://svn.apache.org/viewvc/river/tck/src/com/sun/jini/compat/start/ActivateWrapper.java?rev=1234278&view=auto
==============================================================================
--- river/tck/src/com/sun/jini/compat/start/ActivateWrapper.java (added)
+++ river/tck/src/com/sun/jini/compat/start/ActivateWrapper.java Sat Jan 21 07:28:27 2012
@@ -0,0 +1,744 @@
+/*
+ * 
+ * Copyright 2005 Sun Microsystems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package com.sun.jini.compat.start;
+
+import com.sun.jini.debug.Debug;
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.rmi.MarshalException;
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.StubNotFoundException;
+import java.rmi.UnmarshalException;
+import java.rmi.activation.Activatable;
+import java.rmi.activation.ActivationDesc;
+import java.rmi.activation.ActivationException;
+import java.rmi.activation.ActivationGroup;
+import java.rmi.activation.ActivationGroupID;
+import java.rmi.activation.ActivationID;
+import java.rmi.activation.ActivationSystem;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteRef;
+import java.security.AccessController;
+import java.security.cert.Certificate;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.Security;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.WeakHashMap;
+
+/**
+ * A wrapper for activatable objects, providing separation of the import
+ * codebase (where the server classes are loaded from by the activation
+ * group) from the export codebase (where clients should load classes from
+ * for stubs, etc.) and providing an independent security policy file for
+ * each activatable object. Multiple activatable objects can be placed in
+ * the same activation group, each with distinct codebases and policies.
+ * <p>
+ * This wrapper class is assumed to be available directly in the activation
+ * group VM; that is, it is assumed to be in the application classloader,
+ * the extension classloader, or the boot classloader, rather than being
+ * downloaded. Since this class also needs considerable permissions, the
+ * easiest thing to do is to make it an installed extension.
+ * <p>
+ * This wrapper class performs a security check to control what 
+ * policy files can be used. It does this by querying the virtual
+ * machine's (global) policy for <code>SharedActivationPolicyPermission</code>
+ * grants. The service's <code>ActivateDesc.importLocation</code> is used as 
+ * the <code>CodeSource</code> for selecting the appropriate permission set to 
+ * check against. If multiple codebases are used, then all the codebases must
+ * have the necessary <code>SharedActivationPolicyPermission</code> grants.
+ * <p>
+ * An example of how to use this wrapper:
+ * <pre>
+ * ActivateWrapper.Created created 
+ *     = ActivateWrapper.register(
+ *		gid,
+ *		new ActivateWrapper.ActivateDesc(
+ *				     "foo.bar.ServiceImpl",
+ *				     "http://myhost:8080/service.jar",
+ *				     "http://myhost:8080/service-dl.jar",
+ *				     "http://myhost:8080/service.policy",
+ *				     new MarshalledObject("/tmp/service_log")),
+ *		true);
+ * Remote myStub         = (Remote)created.stub;
+ * ActivationGroupID gid = created.gid;
+ * ActivationID aid      = created.aid;
+ * </pre>
+ * Clients of this service need to implement the following "shared" activation
+ * constructor:
+ * <pre>
+ * public Constructor (ActivationID activationID, 
+ *                     MarshalledObject data,
+ *                     SharedActivation sa)
+ *</pre>
+ * where the first two parameters are the same as those in the normal activation
+ * constructor. The <code>SharedActivation</code> parameter allows clients
+ * to modify their initialization state with the <code>ActivateWrapper</code>.
+ *
+ * @author Sun Microsystems, Inc.
+ *
+ */
+public class ActivateWrapper implements Remote, Serializable {
+
+    /** Debug property string */
+    private final static String DEBUG_PROP = 
+        "com.sun.jini.compat.start.activatewrapper.debug";
+	
+    /** Debug utility object */
+    private final static Debug debug = 
+	(Debug)AccessController.doPrivileged(Debug.getDebugAction(DEBUG_PROP));
+
+    /** <tt>PrintWriter</tt> handle for class loader related messages */
+    private static final PrintWriter dbgLoader = debug.getWriter("loader");
+
+    /** <tt>PrintWriter</tt> handle for class initialization related messages */
+    private static final PrintWriter dbgInit = debug.getWriter("init");
+
+    /** <tt>PrintWriter</tt> handle for security related messages */
+    private static final PrintWriter dbgSecurity = debug.getWriter("security");
+
+    /**
+     * Map which contains the list of objects registered (i.e. activated)
+     * with the wrapper.
+     */
+    private static Map registrants = Collections.synchronizedMap(new HashMap());
+
+    /**
+     * The Policy object that aggregates all of the individual Policy
+     * objects of each activatable object.
+     */
+    private static AggregatePolicy globalPolicy;
+
+    /**
+     * The real activatable object.
+     */
+    private /*final*/ Object impl;
+
+    /**
+     * Client-side interface used to get/set the initialization
+     * data being wrapped by the <code>ActivateWrapper</code> class. 
+     * Note that the activation subsystem contains only direct reference to
+     * <code>ActivateWrapper</code>. 
+     */
+    private static SharedActivation sharedActivation =
+	new SharedActivation() {
+	    public void setInitializationData(ActivationID aid,
+		                              MarshalledObject data)
+                throws ActivationException, RemoteException
+            {
+                ActivateWrapper.setInitializationData(aid, data);
+	    }
+
+	    public ActivateDesc getActivateDesc(ActivationID aid)
+		throws ActivationException, RemoteException
+	    {
+		 return ActivateWrapper.getActivateDesc(aid);
+	    }
+	};
+
+    /**
+     * The parameter types for the activation constructor.
+     */
+    private static final Class[] actTypes = {
+	ActivationID.class, MarshalledObject.class, SharedActivation.class
+    };
+
+    /**
+     * Descriptor for registering a wrapped activatable object. This
+     * descriptor gets stored as the <code>MarshalledObject</code> 
+     * initialization data in the <code>ActivationDesc</code>.
+     */
+    public static class ActivateDesc implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+	/**
+	 * The activatable object's class name.
+	 */
+	public final String className;
+	/**
+	 * The codebase where the server classes are loaded from by the
+	 * activation group.
+	 */
+	public final String importLocation;
+	/**
+	 * The codebase where clients should load classes from for stubs, etc.
+	 */
+	public final String exportLocation;
+	/**
+	 * The security policy filename or URL.
+	 */
+	public final String policy;
+	/**
+	 * The activatable object's initialization data.
+	 */
+	public final MarshalledObject data;
+
+	/**
+	 * Trivial constructor.
+	 */
+	public ActivateDesc(String className,
+			    String importLocation,
+			    String exportLocation,
+			    String policy,
+			    MarshalledObject data)
+	{
+	    this.className = className;
+	    this.importLocation = importLocation;
+	    this.exportLocation = exportLocation;
+	    this.policy = policy;
+	    this.data = data;
+	}
+        // Javadoc inherited from supertype
+	public String toString() {
+	    return "[className=" + className + ","
+	        + "importLocation=" + importLocation + ","
+	        + "exportLocation=" + exportLocation + ","
+	        + "policy=" + policy + ","
+	        + "data=" + data + "]";
+	}
+    }
+
+    /**
+     * A simple subclass of URLClassLoader that overrides 
+     * <code>getURLs()</code> to
+     * return the URLs of the export codebase. <code>getURLs()</code>
+     * is called by the RMI subsystem in order to annotate objects
+     * leaving the virtual machine.
+     */
+    private static class ExportClassLoader extends URLClassLoader {
+	private final URL[] exportURLs;
+
+	public ExportClassLoader(URL[] importURLs,URL[] exportURLs) {
+	    super(importURLs);
+	    this.exportURLs = exportURLs;
+	}
+
+	public URL[] getURLs() {
+	    return (URL[])exportURLs.clone();
+	}
+    }
+
+    /**
+     * A security policy that obtains its permissions by allowing a Policy
+     * object to be associated with an ExportClassLoader instance, and
+     * using the context classloader of the calling thread as the starting
+     * point to search for an ExportClassLoader and then consult the
+     * associated Policy object for the permissions.
+     */
+    private static class AggregatePolicy extends Policy {
+	/**
+	 * The default Policy to use, if an ExportClassLoader is not found.
+	 * This is whatever Policy exists prior to switching to an
+	 * AggregatePolicy.
+	 */
+	private final Policy defaultPolicy = Policy.getPolicy();
+	/**
+	 * Weak map from ExportClassLoader to Policy.
+	 */
+	private final WeakHashMap map = new WeakHashMap();
+
+	/**
+	 * Associate a policy with an ExportClassLoader.
+	 */
+	void addPolicy(ClassLoader cl, Policy policy) {
+	    synchronized (map) {
+		map.put(cl, policy);
+	    }
+	}
+	
+
+	/**
+	 * Start with the context classloader, search up until an
+	 * ExportClassLoader is found, and use the associated Policy.
+	 * If no ExportClassLoader is found, use the default Policy.
+	 */
+	public PermissionCollection getPermissions(CodeSource codesource) {
+	    if (dbgSecurity != null) {
+	        dbgSecurity.println("AggregatePolicy::getPermissions "
+		    + "Getting permissions for code source " + codesource);
+	    }
+	    ClassLoader cl = Thread.currentThread().getContextClassLoader();
+	    while (cl != null && !(cl instanceof ExportClassLoader)) {
+		  cl = cl.getParent();
+	    }
+	    Policy policy;
+	    synchronized (map) {
+		policy = (Policy)map.get(cl);
+	    }
+	    if (policy == null)
+		policy = defaultPolicy;
+	    PermissionCollection pc = policy.getPermissions(codesource);
+	    if (dbgSecurity != null) {
+	        dbgSecurity.println("AggregatePolicy::getPermissions "
+		    + "Permissions:" + pc);
+	    }
+	    return pc;
+	}
+        // Javadoc inherited from supertype
+	public void refresh() {
+	    // XXX refresh every policy in the map?
+	}
+    }
+    
+    /** 
+     *  Data structure used by the <code>register</code> method to
+     *  return multiple values (such as the service reference and the
+     *  <code>ActivationID</code> of the service).
+     */
+    public static class Created {
+        /** The activation group id of the service */
+        public final ActivationGroupID gid;
+	
+        /** The activation id of the service */
+        public final ActivationID aid;
+        
+	/** The reference to the proxy of the created service */
+        public final Object stub;
+        
+	/** Constructs an instance of this class.
+         * @param gid   activation group id of the created service
+         * @param aid   activation id of the created service
+         * @param proxy reference to the proxy of the created service
+         */
+        public Created(ActivationGroupID gid, ActivationID aid, Object stub) {
+            this.gid  = gid;
+            this.aid  = aid;
+            this.stub = stub;
+        }//end constructor
+    }
+
+    /**
+     * The constructor required by activation. On the first activation
+     * of any wrapper instance, replace the VM's <code>Policy</code> object 
+     * with an <code>AggregatePolicy</code>. Create an 
+     * <code>ExportClassLoader</code> using the import and
+     * export codebases from the <code>ActivateDesc</code>, check import 
+     * codebase(s) for policy permission, create a new <code>Policy</code> from
+     * the policy specified in the <code>ActivateDesc</code>, associate the two, 
+     * load the real activatable object's class, and call its shared activation
+     * constructor with the context classloader set to the 
+     * <code>ExportClassLoader</code>.
+     */
+    public ActivateWrapper(ActivationID id, MarshalledObject data)
+	throws Exception
+    {
+     try {
+	if (dbgInit != null) {
+	    dbgInit.println("ActivateWrapper() -- started");
+	    System.getProperties().list(dbgInit);
+	}
+
+	ActivateDesc desc = (ActivateDesc)data.get();
+        if (dbgInit != null) {
+	    dbgInit.println("ActivateWrapper: ActivateDesc: " + desc);
+	}
+
+	ExportClassLoader cl = null;
+	URL[] importUrls = null;
+	URL[] exportUrls = null;
+        try {
+	    importUrls = parseURLs(desc.importLocation);
+	    exportUrls = parseURLs(desc.exportLocation);
+	    cl = new ExportClassLoader(importUrls, exportUrls);
+	    if (dbgLoader != null) {
+                dbgLoader.println("ActivateWrapper: Created ExportClassLoader "
+		    + cl);
+	    }
+        } catch (Exception e) {
+	    System.err.println("Problem creating export class loader" + e);
+	    throw e;
+	}
+	
+	checkPolicyPermission(desc.policy, importUrls);
+	
+	Class pc = Class.forName(Security.getProperty("policy.provider"));
+	if (dbgInit != null) {
+	    dbgInit.println("ActivateWrapper: Obtained policy provider: " + pc);
+        }
+	synchronized (ActivateWrapper.class) {
+	    String val = System.getProperty("java.security.policy");
+	    System.setProperty("java.security.policy", desc.policy);
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Set policy to: "
+		    + desc.policy);
+            }
+	    Policy policy;
+	    try {
+	        // Create new policy object based on current desc.policy
+		policy = (Policy)pc.newInstance();
+	    } finally { // Reset policy to original setup
+		if (val == null)
+		    System.getProperties().remove("java.security.policy");
+		else
+		    System.setProperty("java.security.policy", val);
+	    }
+	    if (globalPolicy == null) { // supplant global policy 1st time through
+		globalPolicy = new AggregatePolicy();
+		Policy.setPolicy(globalPolicy);
+	    }
+	    globalPolicy.addPolicy(cl, policy);
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Added policy to global set");
+            }
+	}
+	Thread t = Thread.currentThread();
+	ClassLoader ccl = t.getContextClassLoader();
+        if (dbgLoader != null) {
+            dbgLoader.println("ActivateWrapper: Saved current context class "
+	        + "loader " + ccl);
+	}
+
+	t.setContextClassLoader(cl);
+	if (dbgLoader != null) {
+            dbgLoader.println("ActivateWrapper: New context class loader set to "
+		+ cl);
+	}
+
+	try {
+	    boolean initialize = false;
+	    Class ac = Class.forName(desc.className, initialize, cl);
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Got impl class: " + ac);
+            }
+
+	    Constructor cons = ac.getConstructor(actTypes);
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Got impl cons: " + cons);
+            }
+
+    	    impl = cons.newInstance(new Object[]{id, desc.data, sharedActivation});
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Got impl instance: " + impl);
+            }
+
+    	    register(impl);
+  	    if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: Registered impl");
+            }
+
+        } catch (Exception e) {
+            System.err.println("Problem creating impl class: " + e);
+            throw e;
+	} finally {
+	    t.setContextClassLoader(ccl);
+	    if (dbgLoader != null) {
+                dbgLoader.println("ActivateWrapper: Reset class loader to "
+		    + ccl);
+	    }
+
+	}
+  	if (dbgInit != null) {
+	    dbgInit.println("ActivateWrapper() -- finished");
+        }
+
+     } catch (Exception e) {
+        System.err.println("Unexpected exception: " + e);
+        throw e;
+     }
+    }
+
+    /*
+     * Add (or replace) the given reference to the list of registered (i.e.
+     * activated) objects.
+     */
+    private static void register(Object r) {
+        //Note: For WeakHashMap impls, don't use key as value since they
+	// are held as strong references.
+        registrants.put(r, r);
+    }
+
+    /*
+     * Remove the given reference from the list of registered (i.e.
+     * activated) objects. Returns <code>true</code> if the reference
+     * was removed and <code>false</code> otherwise.
+     */
+    static boolean unregister(Object r) {
+        return (registrants.remove(r) != null);
+    }
+
+    /*
+     * Return <code>true</code> if the reference is contained in the list
+     * of registered objects and <code>false</code> otherwise.
+     */
+    static boolean registered(Object r) {
+        return (registrants.get(r) != null);
+    }
+
+    /**
+     * Parse the codebase string into a <code>URL[]</code>.
+     */
+    private static URL[] parseURLs(String location)
+	throws MalformedURLException
+    {
+	StringTokenizer st = new StringTokenizer(location);
+	URL[] urls = new URL[st.countTokens()];
+	for (int i = 0; st.hasMoreTokens(); i++) {
+	    urls[i] = new URL(st.nextToken());
+	}
+	return urls;
+    }
+
+    /**
+     * Return the real activatable object so that it will be replaced in
+     * turn by its stub.
+     */
+    private Object writeReplace() {
+	return impl;
+    }
+
+    /**
+     * Analog to Activatable.register for activatable objects that want
+     * to use this wrapper mechanism. This method actively checks that the 
+     * provided activatable class supports the expected constructor. If not, 
+     * then a <code>NoSuchMethodException</code> is thrown.
+     *
+     * @return Created aggregation object that contains the activation 
+     *         group ID, activation ID, and stub/proxy reference to the 
+     *         registered service
+     * 
+     * @throws ClassNotFoundException if there was a problem loading the
+     *             activatable class.
+     * @throws ActivationException    if there was a problem registering
+     *             the activatable class with the activation system
+     * @throws RemoteException        if there was a problem communicating
+     *             with the activation system
+     * @throws NoSuchMethodException  If the activatable class does not 
+     *             support the required shared activation constructor
+     */
+    public static Created register(ActivationGroupID gid,
+				   ActivateDesc desc,
+				   boolean restart)
+	throws ActivationException, RemoteException, 
+	       ClassNotFoundException, NoSuchMethodException
+    {
+        // Verify that class has the proper constructor
+        if (dbgLoader != null) {
+            dbgLoader.println("ActivateWrapper::register: "
+    	        + " Checking " +  desc.className + " for required constructor ");
+        }
+        checkForActivatableConstructor(desc.importLocation, desc.className);    
+    
+	MarshalledObject data;
+	try {
+	    if (dbgLoader != null) {
+	        dbgLoader.println("ActivateWrapper::register: "
+		    + "Marshalling data ");
+	    }
+	    data = new MarshalledObject(desc);
+	} catch (Exception e) {
+	    throw new MarshalException("marshalling ActivateDesc", e);
+	}
+	
+	if (dbgLoader != null) {
+	    dbgLoader.println("ActivateWrapper::register: "
+	        + "Packaging ActivationDesc ");
+	}
+	ActivationDesc adesc =
+	    new ActivationDesc(gid,
+		ActivateWrapper.class.getName(),
+		null,
+		data,
+		restart
+	);      
+	      
+	if (dbgLoader != null) {
+	    dbgLoader.println("ActivateWrapper::register: "
+	        + "registering object"); 
+	}
+	ActivationID aid = ActivationGroup.getSystem().registerObject(adesc);
+
+	if (dbgLoader != null) {
+	    dbgLoader.println("ActivateWrapper::register: "
+	        + "activating object"); 
+	}
+	RemoteObject stub = null;
+        Method m = ClassLoaderUtil.getActivateMethod();
+	try {
+	    stub = (RemoteObject) m.invoke(null, new Object[] { aid });
+	} catch (IllegalAccessException iae) {
+	    throw new ActivationException("Could not access activation method", iae);
+	} catch (java.lang.reflect.InvocationTargetException ite) {
+    	    throw new ActivationException("Could not invoke activation method", ite);
+	}	    
+
+	return new Created(gid, aid, stub);
+    }
+
+    /**
+     * Change the <code>MarshalledObject</code> initialization data for the 
+     * activatable object with the specified activation identifier, assuming 
+     * the object was registered using this wrapper mechanism.
+     */
+    private static void setInitializationData(ActivationID aid,
+					     MarshalledObject data)
+	throws ActivationException, RemoteException
+    {
+    	ActivationSystem sys = ActivationGroup.getSystem();
+	ActivationDesc adesc = sys.getActivationDesc(aid);
+      	ActivateDesc edesc = getActivateDesc(adesc);
+	edesc = new ActivateDesc(edesc.className,
+				 edesc.importLocation,
+				 edesc.exportLocation,
+				 edesc.policy,
+				 data);
+	try {
+	    data = new MarshalledObject(edesc);
+	} catch (Exception e) {
+	    throw new MarshalException("marshalling ActivateDesc", e);
+	}
+	sys.setActivationDesc(aid, new ActivationDesc(adesc.getGroupID(),
+						      adesc.getClassName(),
+						      adesc.getLocation(),
+						      data,
+						      adesc.getRestartMode()));
+    }
+
+    /**
+     * Return the <code>ActivateDesc</code> for the provided 
+     * <code>ActivationID</code>. 
+     */
+    private static ActivateDesc getActivateDesc(ActivationID aid)
+	throws ActivationException, RemoteException
+    {
+	ActivationSystem sys = ActivationGroup.getSystem();
+	ActivationDesc adesc = sys.getActivationDesc(aid);
+	ActivateDesc edesc = getActivateDesc(adesc);
+        return edesc;
+    }
+
+    /**
+     * Return the <code>ActivateDesc</code> for the provided 
+     * <code>ActivationDesc</code>. 
+     */
+    private static ActivateDesc getActivateDesc(ActivationDesc adesc)
+	throws UnmarshalException
+    {
+	ActivateDesc edesc;
+	try {
+	    edesc = (ActivateDesc)adesc.getData().get();
+	} catch (Exception e) {
+	    throw new UnmarshalException("unmarshalling ActivateDesc", e);
+	}
+        return edesc;
+    }
+
+    /**
+     * Checks that all the provided <code>URL</code>s have permission to
+     * use the given policy.
+     */
+    private static void checkPolicyPermission(String policy, URL[] urls) {
+        // Create desired permission object
+	Permission perm = new SharedActivationPolicyPermission(policy);
+	
+	// Loop over all codebases
+	for (int i=0; i < urls.length; i++) {
+            if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: checkPolicyPermission: "
+		    + policy + ", " + urls[i]);
+	    }
+
+            // Get permission set for the current CodeSource
+	    Certificate[] certs = null;
+	    CodeSource cs = new CodeSource(urls[i], certs);
+	    PermissionCollection pers = Policy.getPolicy().getPermissions(cs);
+
+            if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: checkPolicyPermission: "
+		    + cs.toString() + " permissions:" + pers);
+	    }
+	    // Check if current permission set allows desired permission
+	    if(!pers.implies(perm)) {
+                if (dbgInit != null) {
+	            dbgInit.println("ActivateWrapper: checkPolicyPermission: "
+		        + "active security checks failed");
+	        }
+	        throw new SecurityException("CodeSource " + cs
+		    + " does not have required permission: " + perm);
+	    }
+
+            if (dbgInit != null) {
+	        dbgInit.println("ActivateWrapper: checkPolicyPermission: "
+		    + "active security checks passed");
+	    }
+        }
+    }
+    
+    /**
+     * Utility method to check if the activatable object has the required
+     * constructor. It throws an <code>NoSuchMethodException</code> if
+     * the activatable class doesn't support the proper constructor. It 
+     * throws <code>ClassNotFoundException</code> if there was a problem
+     * loading the activatable class.
+     */
+    private static void checkForActivatableConstructor(String location,
+                                                       String name)
+        throws ClassNotFoundException, NoSuchMethodException
+    {
+	Constructor cons;
+	try {
+	    if (dbgLoader != null) {
+	        dbgLoader.println("ActivateWrapper::checkForActivatableConstructor: "
+		    + "loading: " + name + " from " + location);
+	    }
+	    Class cl = RMIClassLoader.loadClass(location, name);
+	    if (dbgLoader != null) {
+	        dbgLoader.println("ActivateWrapper::checkForActivatableConstructor: "
+		    + " Checking " + cl + " for required constructor");
+	    }
+	    
+	    /* 
+	     * Load parameter types through same classloader in order to get
+	     * type compatibility
+	     */
+	    Class[] paramTypes = new Class[actTypes.length];
+	    for (int i=0; i < actTypes.length; i++) {
+	        paramTypes[i] = RMIClassLoader.loadClass(location, 
+		                                         actTypes[i].getName());		
+	    }
+	    // Attempt to retrieve appropriate constructor
+	    cons = cl.getConstructor(paramTypes);
+    	    if (dbgLoader != null) {
+	        dbgLoader.println("ActivateWrapper::checkForActivatableConstructor: "
+		    + " Class " + cl + " supports required constructor: " + cons);
+	    }
+	} catch (NoSuchMethodException nsme) {
+	    throw new NoSuchMethodException(
+	        "Class " + name + " does not support required constructor");
+	} catch (MalformedURLException mue) {
+	    throw new ClassNotFoundException("Could not load " + name 
+	        + " from provided codebase: " + location, mue);
+	}
+    }
+}

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