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