You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/05/16 15:52:07 UTC
svn commit: r406944 [13/30] - in
/incubator/harmony/enhanced/classlib/trunk/modules/rmi2: ./ build/ doc/
doc/testing/ doc/testing/rmi http tunneling/ doc/testing/rmi http
tunneling/Results - ITC/ doc/testing/rmi http tunneling/Results - SUN/
doc/testin...
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCData.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCData.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCData.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCData.java Tue May 16 06:51:00 2006
@@ -0,0 +1,207 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.dgc.server;
+
+import java.lang.ref.WeakReference;
+import java.rmi.Remote;
+import java.rmi.dgc.VMID;
+import java.rmi.server.ObjID;
+import java.rmi.server.Unreferenced;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A container class for the information needed by the Server Distributed
+ * Garbage Collector for each exported Object.
+ *
+ * @author Gustavo Petri
+ */
+final class DGCData {
+ /*
+ * Here we can grant that the vmIdExpirationTimeMap variable only be acceced
+ * in an ordered way.
+ */
+
+ /**
+ * The object's {@link java.rmi.server.ObjID}
+ */
+ private ObjID objID;
+
+ /**
+ * A Strong Reference to the exported Object
+ */
+ private Remote StrongRef;
+
+ /**
+ * A Weak Reference to the exported Object
+ */
+ private WeakReference<Remote> weakRef;
+
+ /**
+ * The mapping of {@link java.rmi.dgc.VMID} to the lease time assigned to
+ * that VM.
+ */
+ private Map<VMID, Long> vmIdExpirationTimeMap;
+
+ /**
+ * The Reference Counter (Not necesarily used).
+ */
+ private int dgcCount;
+
+ /**
+ * Creates a {@link ar.org.fitc.rmi.dgc.server.DGCData}
+ *
+ * @param objID
+ * the {@link ObjID} for this Object.
+ * @param weakRef
+ * a <code>WeakReference</code> for the exported Object
+ */
+ public DGCData(ObjID objID, WeakReference<Remote> weakRef) {
+ this.StrongRef = null;
+ this.objID = objID;
+ this.weakRef = weakRef;
+ this.vmIdExpirationTimeMap = Collections
+ .synchronizedMap(new HashMap<VMID, Long>());
+ this.dgcCount = 0;
+ }
+
+ /**
+ * Returns the {@link ObjID} for this Object
+ *
+ * @return the {@link ObjID} for this Object
+ */
+ public final ObjID getObjID() {
+ return objID;
+ }
+
+ /**
+ * Returns the Strong Reference for this Object
+ *
+ * @return a Strong Reference for this Object
+ */
+ public final Object getStrongRef() {
+ return StrongRef;
+ }
+
+ /**
+ * Returns the <code>WeakReference</code> for this Object
+ *
+ * @return a <code>WeakReference</code> for this Object
+ */
+ public final WeakReference<Remote> getWeakRef() {
+ return weakRef;
+ }
+
+ /**
+ * Returns the expirationTime map for this object.
+ *
+ * @return the expirationTime map for this object
+ */
+ public final Map<VMID, Long> getExpirationTimeMap() {
+ return vmIdExpirationTimeMap;
+ }
+
+ /**
+ * A per {@link java.rmi.dgc.DGC#dirty} implementation
+ * of the dirty method
+ *
+ * @param vmid
+ * The {@link java.rmi.dgc.VMID} updated.
+ * @param expirationTime
+ * The time in which the lease time expires
+ * @see java.rmi.dgc.DGC
+ */
+ public final void dirty(VMID vmid, Long expirationTime) {
+
+ if (vmIdExpirationTimeMap.isEmpty()) {
+ StrongRef = weakRef.get();
+ if (StrongRef == null) {
+ /*
+ * Somehow throw an exception. There should have been a problem
+ * in the network.
+ */
+ }
+ }
+ if (!vmIdExpirationTimeMap.containsKey(vmid)) {
+ dgcCount++;
+ }
+ vmIdExpirationTimeMap.put(vmid, expirationTime);
+ return;
+ }
+
+ /**
+ * A per {@link java.rmi.dgc.DGC#clean(ObjID[], long, VMID, boolean)}
+ * implementation of the dirty method
+ *
+ * @param vmid
+ * The {@link java.rmi.dgc.VMID} updated.
+ * @see java.rmi.dgc.DGC
+ */
+ public final void clean(VMID vmid) {
+
+ if (vmIdExpirationTimeMap.containsKey(vmid)) {
+ vmIdExpirationTimeMap.remove(vmid);
+ dgcCount--;
+ if (vmIdExpirationTimeMap.isEmpty()) {
+ if (StrongRef instanceof Unreferenced) {
+ ((Unreferenced) StrongRef).unreferenced();
+ }
+ StrongRef = null;
+ }
+ }
+ }
+
+ /**
+ * Eliminates the VMID's which's lease times had expired.
+ *
+ * @param time
+ * The time to be taken as bound.
+ * @return the eliminated VMIDs.
+ */
+ public final Set<VMID> removeOlderThan(long time) {
+ /*
+ * The return value is not necesary, is there just for possible
+ * extensions.
+ */
+
+ HashSet<VMID> retVMIDs = new HashSet<VMID>();
+ synchronized (vmIdExpirationTimeMap) {
+ Iterator<VMID> iter = vmIdExpirationTimeMap.keySet().iterator();
+
+ while (iter.hasNext()) {
+ VMID currentVMID = iter.next();
+ Long iterTime = vmIdExpirationTimeMap.get(currentVMID);
+ if (iterTime < time) {
+ iter.remove();
+ dgcCount--;
+ if (vmIdExpirationTimeMap.isEmpty()) {
+ if (StrongRef instanceof Unreferenced) {
+ ((Unreferenced) StrongRef).unreferenced();
+ }
+ StrongRef = null;
+ }
+ retVMIDs.add(currentVMID);
+ }
+ }
+ }
+
+ return retVMIDs;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCData.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCDataTable.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCDataTable.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCDataTable.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCDataTable.java Tue May 16 06:51:00 2006
@@ -0,0 +1,200 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.dgc.server;
+
+import java.lang.ref.WeakReference;
+import java.rmi.Remote;
+import java.rmi.dgc.Lease;
+import java.rmi.dgc.VMID;
+import java.rmi.server.ObjID;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * A table implementation that groups all the exported objects to be eventually
+ * Garbage Collected. It provides the the functionality needed by the
+ * Distributed Garbage Collector to the
+ * {@link ar.org.fitc.rmi.dgc.server.DGCImpl} class.
+ *
+ * @author Gustavo Petri
+ */
+final class DGCDataTable {
+
+ /**
+ * Mapping from {@link java.rmi.server.ObjID} to it's corresponding
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} information.
+ */
+ private Map<ObjID, DGCData> objIdIndex;
+
+ /**
+ * Mapping from a {@link java.lang.ref.WeakReference} to the
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} of it's referee. Used for
+ * clean up after the object has actually been collected.
+ */
+ private Map<WeakReference<Remote>, DGCData> weakRefIndex;
+
+ /**
+ * The maximun time this server will grant a lease to a client. Specified by
+ * the java.rmi.dgc.leaseValue property
+ */
+ private static Long leaseProperty;
+
+ static {
+ leaseProperty =
+ PropertiesReader.readLong("java.rmi.dgc.leaseValue", 600000);
+ }
+
+ /**
+ * Constructs an instance of this class.
+ */
+ public DGCDataTable() {
+ super();
+ objIdIndex =
+ Collections.synchronizedMap(new HashMap<ObjID, DGCData>());
+ weakRefIndex =
+ new ConcurrentHashMap<WeakReference<Remote>, DGCData>();
+ }
+
+ /**
+ * Returns the {@link ar.org.fitc.rmi.dgc.server.DGCData} corresponding to
+ * the given {@link java.rmi.server.ObjID}
+ *
+ * @param objID
+ * Object Identifier for which the
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} is needed.
+ * @return the {@link ar.org.fitc.rmi.dgc.server.DGCData} for the given
+ * {@link java.rmi.server.ObjID}
+ */
+ public final DGCData getByObjID(ObjID objID) {
+ return objIdIndex.get(objID);
+ }
+
+ /**
+ * Returns the {@link ar.org.fitc.rmi.dgc.server.DGCData} corresponding to
+ * the Object refereed by the given {@link java.lang.ref.WeakReference}
+ *
+ * @param wRef
+ * WeakReference for the object whichs
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} is needed.
+ * @return the {@link ar.org.fitc.rmi.dgc.server.DGCData} for the Object
+ * refereed by the given {@link java.rmi.server.ObjID}
+ */
+ public final DGCData getByWeakRef(WeakReference wRef) {
+ return weakRefIndex.get(wRef);
+ }
+
+ /**
+ * @param ids
+ * ObjID's to be renewed
+ * @param lease
+ * The time requested by the client
+ * @param vmid
+ * the clients vmid
+ * @return the Lease granted by the server
+ * @see java.rmi.dgc.DGC
+ */
+ public final Lease dirty(ObjID[] ids, Lease lease, VMID vmid) {
+
+ Long expirationTime;
+ Lease ret;
+ if (lease.getValue() <= leaseProperty) {
+ expirationTime = System.currentTimeMillis() + lease.getValue();
+ ret = lease;
+ } else {
+ expirationTime = System.currentTimeMillis() + leaseProperty;
+ ret = new Lease(vmid, leaseProperty);
+ }
+
+ if (vmid == null) {
+ vmid = new VMID();
+ }
+
+ for (ObjID objID : ids) {
+ if (objIdIndex.containsKey(objID)) {
+ objIdIndex.get(objID).dirty(vmid, expirationTime);
+ } else {
+ /*
+ * It shouldn't be possible to make a dirty call on an
+ * unexported object.
+ */
+ throw new AssertionError();
+ }
+
+ }
+ return ret;
+ }
+
+ /**
+ * @param ids
+ * ObjID's to be renewed
+ * @param vmid
+ * the clients vmid
+ * @see java.rmi.dgc.DGC
+ */
+ public final void clean(ObjID[] ids, VMID vmid) {
+ for (ObjID objID : ids) {
+ if (objIdIndex.containsKey(objID)) {
+ objIdIndex.get(objID).clean(vmid);
+ } else {
+ /*
+ * It shouldn't be possible to make a clean call on an
+ * unexported object.
+ */
+ throw new AssertionError();
+ }
+ }
+ }
+
+ /**
+ * Registers an exported object to be evetually Garbage Collected.
+ *
+ * @param objID
+ * the Objects {@link java.rmi.server.ObjID}
+ * @param weakRef
+ * a WeakReference to the exported Object
+ */
+ public final void register(ObjID objID, WeakReference<Remote> weakRef) {
+ DGCData exportedRemote = new DGCData(objID, weakRef);
+ weakRefIndex.put(exportedRemote.getWeakRef(), exportedRemote);
+ objIdIndex.put(objID, exportedRemote);
+ }
+
+ /**
+ * Returns the {@link java.rmi.server.ObjID} to
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} map.
+ *
+ * @return the {@link java.rmi.server.ObjID} to
+ * {@link ar.org.fitc.rmi.dgc.server.DGCData} map.
+ */
+ public final Map<ObjID, DGCData> getObjIDMap() {
+ return objIdIndex;
+ }
+
+ /**
+ * Unregisters an exported object from the Distributed Garbage Collector.
+ *
+ * @param objID
+ * the Objects {@link java.rmi.server.ObjID} to be unregistered
+ */
+ public final void remove(ObjID objID) {
+ weakRefIndex.remove(objIdIndex.get(objID).getWeakRef());
+ objIdIndex.remove(objID);
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCDataTable.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCImpl.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCImpl.java Tue May 16 06:51:00 2006
@@ -0,0 +1,255 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.dgc.server;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.dgc.DGC;
+import java.rmi.dgc.Lease;
+import java.rmi.dgc.VMID;
+import java.rmi.server.ObjID;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ar.org.fitc.rmi.dgc.DGCScheduledGC;
+import ar.org.fitc.rmi.runtime.RemoteReferenceManager;
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * Implementation of the {@link java.rmi.dgc.DGC} interface
+ *
+ * @author Gustavo Petri
+ */
+public final class DGCImpl extends Thread implements DGC {
+
+ /**
+ * This queue is used for ExportedObjects Garbage Collection purposes. Whan
+ * an exported object is collected by the local garbage collector its
+ * WeakReference will be queued for cleanup purposes in this queue.
+ */
+ private ReferenceQueue<Remote> exportedDGCQueue;
+
+ /**
+ * This Table holds all the needed information about the exported objects to
+ * be collected.
+ */
+ private DGCDataTable dgcDataTable;
+
+ /**
+ * This Table holds the sequence numbers to verify the ordering of the dirty
+ * and clean calls.
+ */
+ private ConcurrentHashMap<VMID, Pair<Long, Long>> seqNumTable;
+
+ /**
+ * Timer used to run Threads executing periodic clean-up actions
+ */
+ private Timer timer;
+
+ /**
+ * Interval used to check if the lease times of the Garbage Collector had
+ * expired Specifed by the ar.org.fitc.rmi.dgc.checkInterval
+ */
+ private static Long checkInterval;
+
+ /**
+ * Lease Time specified for this Serve Specifed by the
+ * java.rmi.dgc.leaseValue property
+ */
+ private static Long leaseProperty;
+
+ /*
+ * Properties setup.
+ */
+ static {
+ checkInterval = PropertiesReader.readLong(
+ "ar.org.fitc.rmi.dgc.checkInterval", 300000);
+
+ leaseProperty = PropertiesReader.readLong(
+ "java.rmi.dgc.leaseValue", 600000);
+ }
+
+ /**
+ * Starts all the periodic actions and Starts the local Garbage Collector
+ */
+ public DGCImpl() {
+
+ super("rmi.dgc.server.DGCImpl");
+ exportedDGCQueue = new ReferenceQueue<Remote>();
+ dgcDataTable = new DGCDataTable();
+ seqNumTable = new ConcurrentHashMap<VMID, Pair<Long, Long>>();
+ timer = new Timer("rmi.dgc.server.CleanUpTimer", true);
+ try {
+ timer.schedule(new CleanTask(), checkInterval, checkInterval);
+ timer.schedule(new RipSequenceNumbersTask(), 2 * leaseProperty,
+ 2 * leaseProperty);
+ DGCScheduledGC.startGC();
+ } catch (Exception e) {
+ // There is no chance that this try will fail unless the clean
+ // method be errased.
+ e.printStackTrace();
+ }
+ /*
+ * Runs the Thread that removes exported Objects out of scope and not
+ * being used remotelly.
+ */
+ this.setDaemon(true);
+ this.start();
+ }
+
+ /**
+ * Registers a new exported Object for Garbage Collection.
+ *
+ * @param objID
+ * The {@link java.rmi.server.ObjID} of the Object
+ * @param obj
+ * The Object to be registered
+ */
+ public final void register(ObjID objID, Remote obj) {
+ dgcDataTable.register(objID, new WeakReference<Remote>(obj,
+ exportedDGCQueue));
+ }
+
+ /**
+ * @see java.rmi.dgc.DGC#clean FIXME boolean strong is not used
+ */
+ public final void clean(ObjID[] ids, long sequenceNum, VMID vmid,
+ @SuppressWarnings("unused")
+ boolean strong) {
+ /*
+ * REVIEW: When the strong parameter is not setted and the VMID making
+ * the clean call does not hold any reference to other locally exported
+ * object the Sequence Number for that VMID could be erased. This would
+ * require that there exists a way to recognize every ObjectID used by a
+ * particular VMID. We have chosen not to hold that table, but instead
+ * erase sequence Numbers for "old enough" VMID's.
+ */
+
+ if (seqNumTable.containsKey(vmid)
+ && sequenceNum > (Long) seqNumTable.get(vmid).getFirst()) {
+ seqNumTable.put(vmid, new Pair<Long, Long>(new Long(sequenceNum),
+ System.currentTimeMillis() + 2 * leaseProperty));
+ dgcDataTable.clean(ids, vmid);
+ } else {
+ // FIXME Just ignore the call?
+ }
+ }
+
+ /**
+ * @see java.rmi.dgc.DGC#dirty
+ */
+ public final Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) {
+ VMID vmid = lease.getVMID();
+ if (vmid == null) {
+ vmid = new VMID();
+ }
+
+ if ((seqNumTable.containsKey(vmid) && sequenceNum > (Long) seqNumTable
+ .get(vmid).getFirst())
+ || (!seqNumTable.containsKey(vmid))) {
+ seqNumTable.put(vmid, new Pair<Long, Long>(new Long(sequenceNum),
+ System.currentTimeMillis() + 2 * leaseProperty));
+ return dgcDataTable.dirty(ids, lease, vmid);
+ } // else Just ignore the call?
+ return null;
+ }
+
+ /**
+ * Eliminates the VMIDs with expired lease times.
+ */
+
+ /**
+ * Unexports the objects that have no more references and that have been
+ * locally Garbage Collected.
+ */
+ @Override
+ public final void run() {
+ RemoteReferenceManager rrm = RemoteReferenceManager
+ .getRemoteReferenceManager();
+
+ /*
+ * Note that this loop is setted to true since the DGC only needs to
+ * stop working when the Client process ends, for that purpose this
+ * thread is set as daemon.
+ */
+ while (true) {
+ try {
+ WeakReference<?> weak = (WeakReference<?>) exportedDGCQueue
+ .remove();
+ ObjID objID = dgcDataTable.getByWeakRef(weak).getObjID();
+ rrm.unexportObjectDGC(objID);
+ dgcDataTable.remove(objID);
+ } catch (InterruptedException e) {
+ // TODO: handle exception
+ e.printStackTrace();
+ } catch (NoSuchObjectException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Cleans up the list of Sequence Numbers
+ *
+ * @see java.rmi.dgc.DGC
+ */
+ private final class RipSequenceNumbersTask extends TimerTask {
+
+ @Override
+ public final void run() {
+ Long currentTime = System.currentTimeMillis();
+
+ Enumeration<VMID> keys = seqNumTable.keys();
+
+ while (keys.hasMoreElements()) {
+ VMID key = keys.nextElement();
+ if (seqNumTable.get(key).getSecond() < currentTime) {
+ seqNumTable.remove(key);
+ }
+ }
+ }
+ }
+
+ /**
+ * Eliminates the VMID's which lease time has expired.
+ */
+ private final class CleanTask extends TimerTask {
+
+ @Override
+ public final void run() {
+ /*
+ * REVIEW: This method might be too expensive in performance.
+ */
+ Long currentTime = System.currentTimeMillis();
+ Map<ObjID, DGCData> objIDMap = dgcDataTable.getObjIDMap();
+ synchronized (objIDMap) {
+ for (ObjID objID : objIDMap.keySet()) {
+ if (objIDMap.containsKey(objID)) {
+ DGCData objData = objIDMap.get(objID);
+ objData.removeOlderThan(currentTime);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/dgc/server/DGCImpl.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl.java Tue May 16 06:51:00 2006
@@ -0,0 +1,360 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.registry;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.StubNotFoundException;
+import java.rmi.registry.Registry;
+import java.rmi.server.ObjID;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.ServerRef;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ar.org.fitc.rmi.runtime.RemoteReferenceManager;
+import ar.org.fitc.rmi.server.UnicastRemoteRef2Impl;
+import ar.org.fitc.rmi.server.UnicastRemoteRefImpl;
+import ar.org.fitc.rmi.server.UnicastServerRef2Impl;
+import ar.org.fitc.rmi.server.UnicastServerRefImpl;
+import ar.org.fitc.rmi.transport.Endpoint;
+import ar.org.fitc.rmi.transport.TransportManager;
+
+/**
+ * This class is the implementation for the specified <code>Registry</code>
+ * interface.
+ *
+ * @author Gonzalo Ortega
+ *
+ */
+public final class RegistryImpl implements Registry {
+
+ private Map<String, Remote> registryTable;
+
+ private Set<String> localIPs;
+
+ /**
+ * Creates a new instance of RegistryImpl
+ */
+ public RegistryImpl() {
+ registryTable = new ConcurrentHashMap<String, Remote>();
+ localIPs = new HashSet<String>();
+ setLocalIPs();
+ }
+
+ /**
+ * Returns all keys present in the registry in a String array.
+ *
+ * @return The list of keys bound to the registry
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final String[] list() throws RemoteException, AccessException {
+ Set<String> keys = registryTable.keySet();
+ String[] result = new String[keys.size()];
+ keys.toArray(result);
+ return result;
+ }
+
+ /**
+ * Returns the associated stub for the received key, or an exception if no
+ * stub is present for that key
+ *
+ * @param name
+ * The key used to bind the remote stub in the registry
+ * @return The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws NotBoundException
+ * If the key is not found in the registry
+ */
+ public final Remote lookup(String name) throws RemoteException,
+ NotBoundException, AccessException {
+ if (name == null) {
+ throw new NullPointerException("The String name is null.");
+ }
+ if (!(registryTable.containsKey(name))) {
+ throw new NotBoundException(
+ "There isn't any object bound in the registry with that key.");
+ }
+ return registryTable.get(name);
+ }
+
+ /**
+ * Puts the received key <code>name</code> and the stub <code>obj</code>
+ * in this registry, or throws an exception if the received key is already
+ * present in the registry.
+ *
+ * @param name
+ * The key that will be used to lookup the remote object
+ * @param obj
+ * The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AlreadyBoundException
+ * if <code>name</code> is already present in the table
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void bind(String name, Remote obj) throws RemoteException,
+ AlreadyBoundException, AccessException {
+
+ checkAccessPrivilegies();
+ if (name == null || obj == null) {
+ throw new NullPointerException(
+ "Either String name or Remote object are null.");
+ }
+ if (registryTable.containsKey(name)) {
+ throw new AlreadyBoundException("The key " + name
+ + " already exists in the registry.");
+ }
+ registryTable.put(name, obj);
+
+ }
+
+ /**
+ * Puts the received key <code>name</code> and the stub <code>obj</code>
+ * in this registry.
+ *
+ * @param name
+ * The key that will be used to lookup the remote object
+ * @param obj
+ * The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void rebind(String name, Remote obj) throws RemoteException,
+ AccessException {
+ checkAccessPrivilegies();
+ if (name == null || obj == null) {
+ throw new NullPointerException(
+ "Either String name or Remote object are null.");
+ }
+ registryTable.put(name, obj);
+ }
+
+ /**
+ * Removes the stub associated to the key received <code>name</code> from
+ * this registry
+ *
+ * @param name
+ * the name of the binding to remove
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws NotBoundException
+ * if <code>name</code> is not found in the registry
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void unbind(String name) throws RemoteException, NotBoundException,
+ AccessException {
+
+ checkAccessPrivilegies();
+ if (name == null) {
+ throw new NullPointerException("The String name is null.");
+ }
+ if (!(registryTable.containsKey(name))) {
+ throw new NotBoundException(
+ "There isn't any object bound in the registry with that key.");
+ }
+ registryTable.remove(name);
+ }
+
+ /**
+ * Exports the registry implementation in the received port, with the
+ * received socket factories. The exportation procedure is similar to the
+ * procedure implemented for <code>UnicastRemoteObject</code>, but using
+ * the special well-known <code>ObjID</code> for the registry.
+ *
+ * @param port
+ * The port where the registry will listen requests
+ * @param csf
+ * The <code>ClientSocketFactory</code> that will be used to
+ * contact this registry
+ * @param ssf
+ * The <code>ServerSocketFactory</code> used for exportation
+ * @param useType2Ref
+ * Indicates whether the references created during object
+ * exportation should be "UnicastRef" or "UnicastRef2"
+ * @return A stub for this registry implementation
+ * @throws RemoteException
+ */
+ public final Remote exportObject(int port, RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf, boolean useType2Ref)
+ throws RemoteException {
+
+ if (port == 0) {
+ port = Registry.REGISTRY_PORT;
+ }
+ RemoteReferenceManager rrm = RemoteReferenceManager
+ .getRemoteReferenceManager();
+ if (rrm.isExported(this)) {
+ throw new RemoteException("Object already exported.");
+ }
+ TransportManager tm = TransportManager.getTransportManager();
+ ObjID objID = new ObjID(ObjID.REGISTRY_ID);
+ Endpoint ep = tm.export(objID, port, ssf, csf);
+ ServerRef sref;
+ Remote stub;
+ if (useType2Ref) {
+ sref = new UnicastServerRef2Impl(this, objID, ep);
+ stub = rrm.createStub(new UnicastRemoteRef2Impl(objID, ep), this);
+ } else {
+ sref = new UnicastServerRefImpl(this, objID, ep);
+ stub = rrm.createStub(new UnicastRemoteRefImpl(objID, ep), this);
+ }
+ rrm.storeExportData(this, objID, sref, stub);
+ return stub;
+ }
+
+ /**
+ * Creates a new stub for a registry, using the <code>createStub</code>
+ * method from the <code>RemoteReferenceManager.</code> First instantiates
+ * a new <code>RemoteRef</code> with an <code>Endpoint</code> created
+ * starting from the received parameters, and the well-known
+ * <code>ObjID</code> for the Registry.
+ *
+ * @param port
+ * The port that will be used to contact the registry
+ * @param host
+ * The host where the registry is located
+ * @param csf
+ * The <code>ClientSocketFactory</code> that will be used to
+ * contact the registry
+ * @param useType2Ref
+ * Indicates whether the reference used for the new stub should
+ * be "UnicastRef" or "UnicastRef2"
+ * @return A stub for the desired registry
+ * @throws StubNotFoundException
+ * if the creation of the stub for this registry fails
+ */
+ public static final Remote createStub(int port, String host,
+ RMIClientSocketFactory csf, boolean useType2Ref) {
+ ObjID objID = new ObjID(ObjID.REGISTRY_ID);
+ Endpoint ep;
+ if (host == null) {
+ ep = new Endpoint(port, csf);
+ } else {
+ ep = new Endpoint(host, port, csf);
+ }
+ Remote stub;
+ if (useType2Ref) {
+ stub = new RegistryImpl_Stub(new UnicastRemoteRef2Impl(objID, ep));
+ } else {
+ stub = new RegistryImpl_Stub(new UnicastRemoteRefImpl(objID, ep));
+ }
+ return stub;
+ }
+
+ /**
+ * Due to the exportation of multiple registries is not supported at the
+ * moment the equals method must return "true" for any instance of the
+ * <code>RegistryImpl</code> class in order to avoid the exportation of a
+ * new registry.
+ *
+ * @param obj
+ * The object that will be compared for equality
+ * @return <code>true</code> if <code>obj</code> is instance of the
+ * class <code>RegistryImpl</code>, else return
+ * <code>false</code>
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj != null) {
+ if (obj instanceof RegistryImpl) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return The hash code for this object
+ */
+ @Override
+ public final int hashCode() {
+ return RegistryImpl.class.hashCode();
+ }
+
+ /**
+ * Checks if the current client has privilegies to modify the contents of
+ * the registry. All non-local clients should be rejected.
+ *
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ private final void checkAccessPrivilegies() throws AccessException {
+ String hostName;
+ try {
+ hostName = RemoteServer.getClientHost();
+ } catch (ServerNotActiveException e) {
+ // if no remote host is currently executing this method,
+ // then is localhost, and the access should be granted.
+ return;
+ }
+ if (hostName == null) {
+ throw new AccessException("Can not get remote host address.");
+ }
+ if (!localIPs.contains(hostName)) {
+ throw new AccessException(
+ "Registry can not be modified by this host.");
+ }
+ }
+
+ /**
+ * Fills the internal set containing all the local addresses for this host.
+ * This map will be used when the <code>checkAccessPrivilegies</code>
+ * executes.
+ *
+ */
+ private final void setLocalIPs() {
+ Enumeration<NetworkInterface> netInterfaces;
+ Enumeration<InetAddress> inetAddresses;
+ try {
+ netInterfaces = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ return;
+ }
+ // Get all IPs from all network interfaces
+ while (netInterfaces.hasMoreElements()) {
+ inetAddresses = netInterfaces.nextElement().getInetAddresses();
+ while (inetAddresses.hasMoreElements()) {
+ localIPs.add(inetAddresses.nextElement().getHostAddress());
+ }
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl_Stub.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl_Stub.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl_Stub.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl_Stub.java Tue May 16 06:51:00 2006
@@ -0,0 +1,238 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.registry;
+
+import java.lang.reflect.Method;
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.UnexpectedException;
+import java.rmi.registry.Registry;
+import java.rmi.server.RemoteRef;
+import java.rmi.server.RemoteStub;
+
+/**
+ * Generic stub used to contact a remote registry.
+ *
+ * @author Gonzalo Ortega
+ *
+ */
+final class RegistryImpl_Stub extends RemoteStub implements Registry {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ private static final long METHOD_BIND_HASH =
+ 7583982177005850366L;
+
+ private static final long METHOD_LIST_HASH =
+ 2571371476350237748L;
+
+ private static final long METHOD_LOOK_UP_HASH =
+ -7538657168040752697L;
+
+ private static final long METHOD_REBIND_HASH =
+ -8381844669958460146L;
+
+ private static final long METHOD_UNBIND_HASH =
+ 7305022919901907578L;
+
+ private static Method methodBind;
+
+ private static Method methodList;
+
+ private static Method methodLookup;
+
+ private static Method methodRebind;
+
+ private static Method methodUnbind;
+
+
+ static {
+ try {
+ methodBind = Registry.class.getMethod("bind", new Class[] {
+ String.class, Remote.class });
+ methodList = Registry.class.getMethod("list", new Class[] {});
+ methodLookup = Registry.class.getMethod("lookup",
+ new Class[] { String.class });
+ methodRebind = Registry.class.getMethod("rebind", new Class[] {
+ String.class, Remote.class });
+ methodUnbind = Registry.class.getMethod("unbind",
+ new Class[] { String.class });
+ } catch (NoSuchMethodException e) {
+ throw new NoSuchMethodError("stub class initialization failed");
+ }
+ }
+
+ /**
+ * Creates a new instance of RegistryImpl_Stub starting from the received
+ * <code>RemoteRef</code>
+ *
+ * @param ref
+ * The <code>RemoteRef</code> for the remote registry
+ */
+ public RegistryImpl_Stub(RemoteRef ref) {
+ super(ref);
+ }
+
+ /**
+ * Puts the received key <code>name</code> and the stub <code>obj</code>
+ * in this registry, or throws an exception if the received key is already
+ * present in the registry.
+ *
+ * @param name
+ * The key that will be used to lookup the remote object
+ * @param obj
+ * The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AlreadyBoundException
+ * if <code>name</code> is already present in the table
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void bind(String name, Remote obj) throws RemoteException,
+ AlreadyBoundException, AccessException {
+ try {
+ ref.invoke(this, methodBind, new Object[] { name, obj },
+ METHOD_BIND_HASH);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (RemoteException e) {
+ throw e;
+ } catch (AlreadyBoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new UnexpectedException("undeclared checked exception", e);
+ }
+ }
+
+ /**
+ * Returns all keys present in the registry in a String array.
+ *
+ * @return The list of keys bound to the registry
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final String[] list() throws RemoteException, AccessException {
+ try {
+ Object result = ref.invoke(this, methodList, null,
+ METHOD_LIST_HASH);
+ return ((String[]) result);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (RemoteException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new UnexpectedException("undeclared checked exception", e);
+ }
+ }
+
+ /**
+ * Returns the associated stub for the received key, or an exception if no
+ * stub is present for that key
+ *
+ * @param name
+ * The key used to bind the remote stub in the registry
+ * @return The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws NotBoundException
+ * If the key is not found in the registry
+ */
+ public final Remote lookup(String name) throws RemoteException,
+ NotBoundException, AccessException {
+ try {
+ Object result = ref.invoke(this, methodLookup,
+ new Object[] { name }, METHOD_LOOK_UP_HASH);
+ return ((Remote) result);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (RemoteException e) {
+ throw e;
+ } catch (NotBoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new UnexpectedException("undeclared checked exception", e);
+ }
+ }
+
+ /**
+ * Puts the received key <code>name</code> and the stub <code>obj</code>
+ * in this registry.
+ *
+ * @param name
+ * The key that will be used to lookup the remote object
+ * @param obj
+ * The remote object associated with <code>name</code>
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void rebind(String name, Remote obj) throws RemoteException,
+ AccessException {
+ try {
+ ref.invoke(this, methodRebind, new Object[] { name, obj },
+ METHOD_REBIND_HASH);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (RemoteException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new UnexpectedException("undeclared checked exception", e);
+ }
+ }
+
+ /**
+ * Removes the stub associated to the key received <code>name</code> from
+ * this registry
+ *
+ * @param name
+ * the name of the binding to remove
+ * @throws RemoteException
+ * if remote communication with the registry failed
+ * @throws NotBoundException
+ * if <code>name</code> is not found in the registry
+ * @throws AccessException
+ * if registry denies the caller access to perform this
+ * operation
+ */
+ public final void unbind(String name) throws RemoteException, NotBoundException,
+ AccessException {
+ try {
+ ref.invoke(this, methodUnbind, new Object[] { name },
+ METHOD_UNBIND_HASH);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (RemoteException e) {
+ throw e;
+ } catch (NotBoundException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new UnexpectedException("undeclared checked exception", e);
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/registry/RegistryImpl_Stub.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RMIDefaultClassLoaderSpi.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RMIDefaultClassLoaderSpi.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RMIDefaultClassLoaderSpi.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RMIDefaultClassLoaderSpi.java Tue May 16 06:51:00 2006
@@ -0,0 +1,387 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.runtime;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RMIClassLoaderSpi;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * This is the default RMI implementation of the
+ * {@link java.rmi.server.RMIClassLoaderSpi} interface. The implementation of
+ * these method it is specified in the
+ * {@link RMIClassLoader}
+ * API.
+ *
+ * @author Gustavo Petri
+ *
+ */
+public class RMIDefaultClassLoaderSpi extends RMIClassLoaderSpi {
+
+ /**
+ * A <code>String</code> that serves as a cache fot the codebaseProp
+ * property.
+ */
+ private String codebaseProp;
+
+ /**
+ * A flag that represents the unexistence of a <code>SecurityManager</code>.
+ */
+ private boolean noSecurityManager;
+
+ /**
+ * The actual <code>SecurityManager</code> instance of the class.
+ */
+ private SecurityManager securityManager;
+
+ /**
+ * This is a mapping between pairs of sorted codebase Strings and
+ * <code>ClassLoader</code> instances to <code>WeakReferences</code> to
+ * the <code>URLClassLoader</code> cached in this table.
+ */
+ private HashMap<Pair<String, ClassLoader>, WeakReference<URLClassLoader>> classLoaderMap;
+
+ /**
+ * Constructs a default {@link java.rmi.server.RMIClassLoaderSpi}
+ * instance and it initializes the private variables.
+ */
+ public RMIDefaultClassLoaderSpi() {
+
+ super();
+ codebaseProp = PropertiesReader.readString("java.rmi.server.codebase");
+ securityManager = System.getSecurityManager();
+ if (securityManager == null) {
+ noSecurityManager = true;
+ } else {
+ noSecurityManager = false;
+ }
+ classLoaderMap =
+ new HashMap<Pair<String, ClassLoader>, WeakReference<URLClassLoader>>();
+ }
+
+ @Override
+ /**
+ * Should construct a Proxy Class that implements all the interfaces passed
+ * as parameter.
+ *
+ * @param codebase
+ * a <code>String</code> that represent the specified directory
+ * @param interfaces
+ * a array of <code>Strings</code> interfaces
+ * @param defaultLoader
+ * responsible for loading classes
+ * @return a Proxy Class that implements all the interfaces
+ * @throws MalformedURLException
+ * no legal protocol could be found in a specification string
+ * @throws ClassNotFoundException
+ * if there is no Classloader for the specified interfaces
+ */
+ public final Class<?> loadProxyClass(String codebase, String[] interfaces,
+ ClassLoader defaultLoader) throws MalformedURLException,
+ ClassNotFoundException {
+ Class<?>[] interfaceClasses = new Class[interfaces.length];
+ ClassLoader notPublicClassloader = null;
+
+ for (int i = 0; i < interfaces.length; i++) {
+ interfaceClasses[i] = loadClass(codebase, interfaces[i],
+ defaultLoader);
+ int modifier = interfaceClasses[i].getModifiers();
+ if (!Modifier.isPublic(modifier)) {
+ if (notPublicClassloader == null) {
+ notPublicClassloader = interfaceClasses[i].getClassLoader();
+ } else if (!notPublicClassloader.equals(interfaceClasses[i]
+ .getClassLoader())) {
+ throw new LinkageError(
+ "There is no Classloader for the specified interfaces");
+ }
+ }
+ }
+ if (notPublicClassloader != null) {
+ try {
+ return Proxy.getProxyClass(notPublicClassloader,
+ interfaceClasses);
+ } catch (Exception e) {
+ throw new LinkageError(
+ "There is no Classloader for the specified interfaces");
+ }
+ }
+ try {
+ ClassLoader cl = getClassLoader(codebase);
+ return Proxy.getProxyClass(cl, interfaceClasses);
+ } catch (IllegalArgumentException e) {
+ try {
+ return Proxy.getProxyClass(defaultLoader, interfaceClasses);
+ } catch (IllegalArgumentException e1) {
+ throw new ClassNotFoundException(
+ "There is no Classloader for the specified interfaces",
+ e);
+ }
+ }
+ }
+
+ @Override
+ /**
+ * Specified in the
+ * {@link java.rmi.server.RMIClassLoader#getDefaultProviderInstance} Method.
+ * Returns the
+ * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html"><code>ClassLoader</code></a>}
+ * which has loaded the Class.
+ *
+ * @param cl
+ * the specified Class
+ * @return the
+ * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html"><code>ClassLoader</code></a>}
+ * which has loaded the Class.
+ */
+ public final String getClassAnnotation(Class cl) {
+
+ java.lang.ClassLoader classLoader = cl.getClassLoader();
+
+ String codebase =
+ PropertiesReader.readString("java.rmi.server.codebase");
+
+ if (classLoader == null) {
+ return codebase;
+ }
+ java.lang.ClassLoader cLoader = classLoader;
+ while (cLoader != null) {
+ if (ClassLoader.getSystemClassLoader().equals(classLoader)) {
+ return codebase;
+ }
+ if (cl != null) {
+ cLoader = cLoader.getParent();
+ }
+ }
+
+ if (classLoader instanceof URLClassLoader
+ && !ClassLoader.getSystemClassLoader().equals(classLoader)) {
+ try {
+ URL urls[] = ((URLClassLoader) classLoader).getURLs();
+ String ret = null;
+
+ /*
+ * FIXME HARD: Check Permissions: If the URLClassLoader was
+ * created by this provider to service an invocation of its
+ * loadClass or loadProxyClass methods, then no permissions are
+ * required to get the associated codebase string. If it is an
+ * arbitrary other URLClassLoader instance, then if there is a
+ * security manager, its checkPermission method will be invoked
+ * once for each URL returned by the getURLs method, with the
+ * permission returned by invoking
+ * openConnection().getPermission() on each URL
+ */
+
+ if (urls != null) {
+ for (URL url : urls) {
+ if (ret == null) {
+ ret = new String(url.toExternalForm());
+ } else {
+ ret += " " + url.toExternalForm();
+ }
+ }
+ }
+
+ return ret;
+ } catch (SecurityException e) {
+ return codebase;
+ }
+ }
+ return codebase;
+ }
+
+ @Override
+ /**
+ * Specified in the {@link java.rmi.server.RMIClassLoader#loadClass(String)}
+ * Method. It loads the class directly.
+ *
+ * @param codebase
+ * a <code>String</code> that represent the specified directory
+ * @param name
+ * of the class.
+ * @param defaultLoader
+ * responsible for loading classes
+ * @return a Proxy Class
+ * @throws MalformedURLException
+ * no legal protocol could be found in a specification string
+ * @throws ClassNotFoundException
+ * if there is no Classloader for the specified interfaces
+ */
+ public final Class<?> loadClass(String codebase, String name,
+ ClassLoader defaultLoader) throws MalformedURLException,
+ ClassNotFoundException {
+ Class<?> ret;
+
+ if (defaultLoader != null) {
+ try {
+ ret = Class.forName(name, false, defaultLoader);
+ } catch (ClassNotFoundException e) {
+ try {
+ ret = Class.forName(name, false, getClassLoader(codebase));
+ } catch (SecurityException e1) {
+ ret = Class.forName(name, false, Thread.currentThread()
+ .getContextClassLoader());
+ }
+ }
+ } else {
+ try {
+ ret = Class.forName(name, false, getClassLoader(codebase));
+ } catch (SecurityException e1) {
+ ret = Class.forName(name, false, Thread.currentThread()
+ .getContextClassLoader());
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ /**
+ * Specified in the
+ * {@link java.rmi.server.RMIClassLoader#getClassLoader(String)} Method.
+ * Returns the corresponding
+ * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html"><code>ClassLoader</code></a>}
+ * to the codebase
+ *
+ * @param codebase
+ * a <code>String</code> that represent the specified directory
+ * @return the corresponding
+ * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html"><code>ClassLoader</code></a>}
+ * @throws MalformedURLException
+ * no legal protocol could be found in a specification string
+ */
+ public final ClassLoader getClassLoader(String codebase)
+ throws MalformedURLException {
+
+ if (!noSecurityManager) {
+ securityManager.checkPermission(
+ new RuntimePermission("getClassLoader"));
+ } else {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ return getClassLoaderFromCodebase(codebase);
+ }
+
+ /**
+ * Specified in the {@link java.rmi.server.RMIClassLoader}.
+ *
+ * @param codebase
+ * a <code>String</code> that represent the specified directory
+ * @return the corresponding
+ * {@link ClassLoader}
+ * @throws MalformedURLException
+ * no legal protocol could be found in a specification string
+ */
+ private final ClassLoader getClassLoaderFromCodebase(String codebase)
+ throws MalformedURLException {
+ ClassLoader classLoader = null;
+
+ String tempCodebase = (codebase == null) ? codebaseProp : codebase;
+ /*
+ * The API Specification always assumes that the property
+ * java.rmi.server.codebase is correctly setted, and it does not specify
+ * what to do when returns null. In this case we always return
+ * Thread.currentThread().getContextClassLoader();
+ */
+
+ if (tempCodebase == null) {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ tempCodebase = sortURLs(tempCodebase);
+ Pair<String, ClassLoader> key = new Pair<String, ClassLoader>(
+ tempCodebase, Thread.currentThread().getContextClassLoader());
+ if (classLoaderMap.containsKey(key)) {
+ classLoader = classLoaderMap.get(key).get();
+ }
+ if (classLoader == null) {
+ URL[] urls = getURLs(codebase);
+ if (urls == null) {
+ return null;
+ }
+ for (URL url : urls) {
+ try {
+ securityManager.checkPermission(url.openConnection()
+ .getPermission());
+ } catch (IOException e) {
+ throw new SecurityException(e);
+ }
+ }
+ classLoader = new URLClassLoader(urls);
+ classLoaderMap.put(key, new WeakReference<URLClassLoader>(
+ (URLClassLoader) classLoader));
+ }
+ return classLoader;
+ }
+
+ /**
+ * Takes a <EM>space separated</EM> list of URL's as a String, and sorts
+ * it. For that purpose the String must be parsed.
+ *
+ * @param urls
+ * a list of URL's
+ * @return an alphabetic order list of URL's
+ */
+ private final static String sortURLs(String urls) {
+ String ret = null;
+
+ if (urls != null) {
+ String[] codebaseSplit = urls.split("( )+");
+ if (codebaseSplit.length > 0) {
+ ret = new String();
+ Arrays.sort(codebaseSplit);
+ for (String url : codebaseSplit) {
+ ret += url + " ";
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Takes a <EM>space separated</EM> list of URL's as a <code>String</code>,
+ * and returns an array of URL's.
+ *
+ * @param urls
+ * a list of URL's as a <code>String</code>
+ * @return an array of URL's
+ * @throws MalformedURLException
+ * no legal protocol could be found in a specification string
+ */
+ private final static URL[] getURLs(String urls) throws MalformedURLException {
+ URL[] realURLs = null;
+
+ if (urls == null) {
+ return realURLs;
+ }
+ String[] codebaseSplit = urls.split("( )+");
+ if (codebaseSplit.length > 0) {
+ realURLs = new URL[codebaseSplit.length];
+ for (int i = 0; i < codebaseSplit.length; i++) {
+ realURLs[i] = new URL(codebaseSplit[i]);
+ }
+ }
+ return realURLs;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RMIDefaultClassLoaderSpi.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RemoteReferenceManager.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RemoteReferenceManager.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RemoteReferenceManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RemoteReferenceManager.java Tue May 16 06:51:00 2006
@@ -0,0 +1,471 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.runtime;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Proxy;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.StubNotFoundException;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.rmi.server.RemoteRef;
+import java.rmi.server.RemoteStub;
+import java.rmi.server.ServerRef;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ar.org.fitc.rmi.dgc.server.DGCImpl;
+import ar.org.fitc.rmi.server.UnicastServerRefImpl;
+import ar.org.fitc.rmi.transport.TransportManager;
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+import ar.org.fitc.rmi.utils.RemoteUtils;
+
+/**
+ * Implements a singleton which provides neccessary funtionality for
+ * remote object exportation, remote object management, stub generation,
+ * call execution, etc.
+ *
+ * @author Gonzalo Ortega
+ *
+ */
+public final class RemoteReferenceManager {
+
+ private static RemoteReferenceManager rrm;
+
+ private Map<ObjID, ServerRef> serverRefsMap;
+
+ private Map<Remote, Pair<Remote, ObjID>> exportedRemotes;
+
+ private DGCImpl dgc;
+
+ /**
+ * Implements the singleton behavior. If there is an instance of
+ * <code>RemoteReferenceManager</code> is returned, else a new instance is
+ * created and returned.
+ *
+ * @return the only <code>RemoteReferenceManager</code> instance
+ */
+ public final static synchronized RemoteReferenceManager getRemoteReferenceManager() {
+ if (rrm == null) {
+ rrm = new RemoteReferenceManager();
+ }
+ return rrm;
+ }
+
+ /**
+ * Creates a new instance of <code>RemoteReferenceManager</code>. This
+ * created instance should be the one and only. (<code>RemoteReferenceManager</code>
+ * is a Singleton object)
+ */
+ private RemoteReferenceManager() {
+ // Initialize internal tables
+ serverRefsMap = new ConcurrentHashMap<ObjID, ServerRef>();
+ exportedRemotes = Collections
+ .synchronizedMap(new WeakHashMap<Remote, Pair<Remote, ObjID>>());
+
+ // Export the Distributed Garbage Collector
+ dgc = new DGCImpl();
+ ObjID objID = new ObjID(ObjID.DGC_ID);
+ UnicastServerRefImpl sref = new UnicastServerRefImpl(dgc, objID, null);
+ storeExportData(null, objID, sref, null);
+ }
+
+ /**
+ * Stores the data generated during object exportation into the
+ * <code>RemoteReferenceManager</code> internal tables
+ *
+ * @param obj
+ * The remote object being exported
+ * @param objID
+ * The <code>ObjID</code> generated for <code>obj</code>
+ * @param sref
+ * The <code>ServerRef</code> generated for <code>obj</code>
+ * @param stub
+ * The stub generated for <code>obj</code>
+ */
+ public final void storeExportData(Remote obj, ObjID objID, ServerRef sref,
+ Remote stub) {
+ serverRefsMap.put(objID, sref);
+ exportedRemotes.put(obj, new Pair<Remote, ObjID>(stub, objID));
+ dgc.register(objID, obj);
+ }
+
+ /**
+ * Returns <code>true</code> if <code>obj</code> has been exported to
+ * the RMI Runtime.
+ *
+ * @param obj
+ * The remote object that could be exported
+ * @return <code>true</code> if <code>obj</code> has been exported to
+ * the RMI Runtime
+ */
+ public final boolean isExported(Remote obj) {
+ if ((exportedRemotes.containsKey(obj))
+ && !(obj instanceof RemoteObjectInvocationHandler)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Receives a dispatch request from the Transport Layer and forwards it to
+ * the appropriate dispatcher object.
+ *
+ * @param objID
+ * The <code>ObjID</code> received in the request
+ * @param hash
+ * The method identificator received in the request
+ * @param args
+ * The arguments received in the request
+ * @return The result of the invocation in the remote object
+ * @throws Exception
+ * If the invocation of the method throws an exception
+ */
+ public final Object executeCall(ObjID objID, long hash, Object[] args)
+ throws Exception {
+ if (objID == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID == null).");
+ }
+ ServerRef sref = serverRefsMap.get(objID);
+ if (sref == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID not found in lookup).");
+ }
+
+ /*
+ * REVIEW: For call execution the instance of ServerRef needed is of
+ * type UnicastServerRefImpl, instead of ServerRef... (ServerRef doesn't
+ * specify the dispach method) Review the casting or the type stored in
+ * the container when the implementation of the Activation framework
+ * takes place.
+ */
+ if (sref instanceof UnicastServerRefImpl) {
+ return ((UnicastServerRefImpl) sref).executeCall(args, hash);
+ }
+ throw new NoSuchObjectException(
+ "Remote server not available (No UnicastServerImpl reference).");
+ }
+
+ /**
+ * Returns a stub for the exported object <code>obj</code>
+ *
+ * @param obj
+ * the remote object that the stub is requested for
+ * @return the stub corresponding to <code>obj</code>
+ * @throws NoSuchObjectException
+ * if there is no stub correspondig to <code>obj</code>
+ */
+ public final Remote getStub(Remote obj) throws NoSuchObjectException {
+ if (obj == null) {
+ throw new NoSuchObjectException(
+ "Invalid (null) Remote server object.");
+ }
+ Pair<Remote, ObjID> data;
+ if ((data = exportedRemotes.get(obj)) != null) {
+ return data.getFirst();
+ }
+ throw new NoSuchObjectException("Stub not found for this object.");
+ }
+
+ /**
+ * Removes the remote object <code>obj</code> from internal tables, and
+ * delegates the unexportation to the Transport Layer, in order to perform
+ * the neccessary cleanup.
+ *
+ * @param obj
+ * The remote object that will be unexported
+ * @param force
+ * if true, unexports the object even if there are pending calls;
+ * if false, only unexports the object if there are no pending
+ * calls
+ * @return true if the remote object was unexported, false otherwise
+ * @throws NoSuchObjectException
+ * if the remote object was not exported
+ */
+ public final boolean unexportObject(Remote obj, boolean force)
+ throws NoSuchObjectException {
+ if (obj == null) {
+ throw new NoSuchObjectException(
+ "Invalid (null) Remote server object.");
+ }
+ Pair<Remote, ObjID> data;
+ if ((data = exportedRemotes.get(obj)) == null) {
+ throw new NoSuchObjectException("Object not exported.");
+ }
+ ObjID objID = data.getSecond();
+
+ TransportManager tm = TransportManager.getTransportManager();
+ if (tm.unexport(objID, force)) {
+ // Remove data for this object from the internal tables
+ serverRefsMap.remove(objID);
+ exportedRemotes.remove(obj);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes the received <code>objID</code> from internal tables, and
+ * delegates the unexportation to the Transport Layer, in order to perform
+ * the neccessary cleanup.
+ *
+ * @param objID
+ * The <code>objID</code> that will be removed
+ * @return true if the remote object was unexported, false otherwise
+ * @throws NoSuchObjectException
+ * if the <code>objID</code> was not found
+ */
+ public final boolean unexportObjectDGC(ObjID objID)
+ throws NoSuchObjectException {
+ if (objID == null) {
+ throw new NoSuchObjectException(
+ "Invalid (null) Remote server object.");
+ }
+ if (!(serverRefsMap.containsKey(objID))) {
+ return true;
+ }
+ TransportManager tm = TransportManager.getTransportManager();
+ if (tm.unexport(objID, true)) {
+ // Remove data for this object from the internal tables
+ serverRefsMap.remove(objID);
+ // Removing data from exportedRemotes is not needed, because it will
+ // be
+ // automatically removed when GC collects the remote object
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the number of arguments received by the method represented by
+ * <code>methodHash</code> in the remote object referenced by
+ * <code>objID</code>
+ *
+ * @param objID
+ * The <code>ObjID</code> received in the request
+ * @param methodHash
+ * The method identificator received in the request
+ * @return the number of arguments of the method
+ * @throws NoSuchObjectException
+ * if there isn't any exported object with the received
+ * <code>ObjID</code>
+ */
+ public final int getArgsCount(ObjID objID, long methodHash)
+ throws NoSuchObjectException {
+ if (objID == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID == null).");
+ }
+ ServerRef sref = serverRefsMap.get(objID);
+ if (sref == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID not found in lookup).");
+ }
+
+ /*
+ * REVIEW: For call execution the instance of ServerRef needed is of
+ * type UnicastServerRefImpl, instead of ServerRef... (ServerRef doesn't
+ * specify the getArgsCount method) Review the casting or the type
+ * stored in the container when the implementation of the Activation
+ * framework takes place.
+ */
+ if (sref instanceof UnicastServerRefImpl) {
+ return ((UnicastServerRefImpl) sref).getArgsCount(methodHash);
+ }
+ throw new NoSuchObjectException(
+ "Remote server not available (No UnicastServerImpl reference).");
+ }
+
+ /**
+ * Returns true if the method represented by <code>methodHash</code> in
+ * the remote object referenced by <code>objID</code> returns any value.
+ * (the return type of the method is different than <code>void</code>)
+ *
+ * @param objID
+ * The <code>ObjID</code> received in the request
+ * @param methodHash
+ * The method identificator received in the request
+ * @return true if the return type of the method is different than
+ * <code>void</code>, otherwise returns false
+ * @throws NoSuchObjectException
+ * if there isn't any exported object with the received
+ * <code>ObjID</code>
+ */
+ public final boolean sendReturnValue(ObjID objID, long methodHash)
+ throws NoSuchObjectException {
+ if (objID == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID == null).");
+ }
+ ServerRef sref = serverRefsMap.get(objID);
+ if (sref == null) {
+ throw new NoSuchObjectException(
+ "Remote server not available (ObjID not found in lookup).");
+ }
+
+ /*
+ * REVIEW: For call execution the instance of ServerRef needed is of
+ * type UnicastServerRefImpl, instead of ServerRef... (ServerRef doesn't
+ * specify the sendReturnValue method) Review the casting or the type
+ * stored in the container when the implementation of the Activation
+ * framework takes place.
+ */
+ if (sref instanceof UnicastServerRefImpl) {
+ return ((UnicastServerRefImpl) sref).sendReturnValue(methodHash);
+ }
+ throw new NoSuchObjectException(
+ "Remote server not available (No UnicastServerImpl reference).");
+ }
+
+ /**
+ * Instantiates and returns a stub for a remote object starting from the
+ * class generated by <code>rmic</code>. If the class is no found, an
+ * exception is thrown.
+ *
+ * @param ref
+ * The remote reference for the stub
+ * @param obj
+ * The object, that the stub will represent
+ * @return a stub for <code>obj</code>
+ * @throws StubNotFoundException
+ * if the stub class is not found, or any other problem arises
+ * during stub instantiation.
+ */
+ public final RemoteStub createRegularStub(RemoteRef ref, Remote obj)
+ throws StubNotFoundException {
+
+ Class stubBaseClass = findStubBaseClass(obj.getClass());
+ String stubClassName = stubBaseClass.getName() + "_Stub";
+ Class[] argsClass = new Class[] { java.rmi.server.RemoteRef.class };
+ Object[] args = new Object[] { ref };
+ Constructor constructor;
+
+ Object stub;
+ try {
+ Class stubClass = Class.forName(stubClassName, true, stubBaseClass
+ .getClassLoader());
+ constructor = stubClass.getConstructor(argsClass);
+ } catch (Exception e) {
+ throw new StubNotFoundException(stubClassName
+ + ": Stub class not found", e);
+ }
+
+ try {
+ stub = constructor.newInstance(args);
+ } catch (Exception e) {
+ throw new StubNotFoundException(
+ "Error during stub instantiation - " + stubClassName, e);
+ }
+
+ if (stub instanceof RemoteStub) {
+ return (RemoteStub) stub;
+ }
+ throw new StubNotFoundException(stubClassName
+ + " doesn't inherits from RemoteStub.");
+ }
+
+ /**
+ * Instantiates and returns a stub either starting from a class generated by
+ * <code>rmic</code>, or creating a dynamic proxy class for the remote
+ * object.
+ *
+ * @param ref
+ * The remote reference for the stub
+ * @param obj
+ * The object, that the stub will represent
+ * @return a stub for <code>obj</code>
+ * @throws StubNotFoundException
+ * If a dynamic proxy can not be instantiated for that object.
+ */
+ public final Remote createStub(RemoteRef ref, Remote obj)
+ throws StubNotFoundException {
+ Remote stub = null;
+ boolean ignoreStubClasses = false;
+ String propertyValue;
+
+ // Verify if the old non-dynamic stubs should be ignored
+ propertyValue = PropertiesReader
+ .readString("java.rmi.server.ignoreStubClasses");
+ if (propertyValue != null) {
+ ignoreStubClasses = propertyValue.equalsIgnoreCase("true");
+ }
+
+ if (!ignoreStubClasses) {
+ try {
+ stub = createRegularStub(ref, obj);
+ return stub;
+ } catch (StubNotFoundException e) {
+ // An error has been produced during regular stub instantiation.
+ // ignore it and try now a dynamic proxy.
+ }
+ }
+
+ Set<Class> remoteSet = (RemoteUtils.getRemoteInterfaces(obj.getClass()));
+ Class[] remoteInterfaces = new Class[remoteSet.size()];
+ remoteSet.toArray(remoteInterfaces);
+
+ try {
+ stub = (Remote) Proxy.newProxyInstance(obj.getClass()
+ .getClassLoader(), remoteInterfaces,
+ new RemoteObjectInvocationHandler(ref));
+ } catch (IllegalArgumentException ex) {
+ throw new StubNotFoundException(
+ "Couldn't create dynamic proxy for " + obj, ex);
+ }
+ return stub;
+ }
+
+ /**
+ * Finds the "root class" according to RMI Specification, wich name will be
+ * used for constructing the name of the stub class that corresponds to the
+ * <code>inspect</code> class.
+ *
+ * @param inspect
+ * the class of the object
+ * @return the root class of the object
+ * @throws StubNotFoundException
+ * If the class does not implement any remote interfaces
+ */
+ // Returns the apropriate root class for a stub of the class received as
+ // parameter.
+ private final Class findStubBaseClass(Class inspect)
+ throws StubNotFoundException {
+ Set<Class> remoteInterfacesList = RemoteUtils
+ .getRemoteInterfaces(inspect);
+
+ do {
+ // Check if the class implements any Remote Interface directly
+ Class[] directInterfacesList = inspect.getInterfaces();
+ for (Class directInterface : directInterfacesList) {
+ if (remoteInterfacesList.contains(directInterface)) {
+ return inspect;
+ }
+ }
+ // The interfaces implemented directly aren't remote interfaces...
+ // check now the interfaces implemented directly by the superclass.
+ inspect = inspect.getSuperclass();
+ } while (inspect != null);
+
+ throw new StubNotFoundException(
+ "The remote object doesn't implement any Remote interfaces.");
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/runtime/RemoteReferenceManager.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/server/ReferenceTypes.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/server/ReferenceTypes.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/server/ReferenceTypes.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/server/ReferenceTypes.java Tue May 16 06:51:00 2006
@@ -0,0 +1,41 @@
+/*
+* Copyright 2005 The Apache Software Foundation or its licensors, as applicable.
+*
+* 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 ar.org.fitc.rmi.server;
+
+/**
+ * This enum holds the string representation for all the remote reference types
+ *
+ * UnicastRef UnicastRef2 UnicastServerRef UnicastServerRef2
+ *
+ * @author Gustavo Petri
+ *
+ */
+public enum ReferenceTypes {
+
+ UNICAST_REF("UnicastRef"), UNICAST_REF2("UnicastRef2"), UNICAST_SERVER_REF(
+ "UnicastServerRef"), UNICAST_SERVER_REF2("UnicastServerRef2");
+
+ private String type;
+
+ private ReferenceTypes(String type) {
+ this.type = type;
+ }
+
+ @Override
+ public final String toString() {
+ return type;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/server/ReferenceTypes.java
------------------------------------------------------------------------------
svn:executable = *