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 = *