You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gh...@apache.org on 2006/05/18 22:01:30 UTC

svn commit: r407625 [12/16] - in /incubator/harmony/enhanced/classlib/trunk/modules/rmi3: ./ doc/ make/ src/ src/common/ src/common/javasrc/ src/common/javasrc/java/ src/common/javasrc/java/rmi/ src/common/javasrc/java/rmi/activation/ src/common/javasr...

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectInfo.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectInfo.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectInfo.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectInfo.java Thu May 18 13:01:22 2006
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.rmi.Remote;
+import java.rmi.dgc.VMID;
+import java.rmi.server.ObjID;
+import java.rmi.server.Unreferenced;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.PrivilegedAction;
+import java.util.Hashtable;
+
+import org.apache.harmony.rmi.common.CreateThreadAction;
+import org.apache.harmony.rmi.common.RMIUtil;
+import org.apache.harmony.rmi.remoteref.UnicastServerRef;
+
+
+/**
+ * Holds info characterizing exported remote objects.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+final class RMIObjectInfo {
+
+    // Reference to remote object.
+    final RMIReference ref;
+
+    // Object ID for remote object.
+    final ObjID id;
+
+    // Stub for remote object.
+    final Remote stub;
+
+    // Server handle for remote object
+    final UnicastServerRef sref;
+
+    // AccessControlContext when this Info was created
+    final AccessControlContext acc;
+
+    // ClassLoader for dispatching calls.
+    final ClassLoader loader;
+
+    // Table where VMIDs are keys and DGCExpirationInfos are values
+    final Hashtable vmidTable = new Hashtable();
+
+    /*
+     * Table of VMID's remembered after DGC.clean() call with strong=true.
+     * VMIDs are keys and Long() representing sequence numbers are values.
+     */
+    final Hashtable rememberedTable = new Hashtable();
+
+    /*
+     * Constructs RemoteObjectInfo holding the specified information.
+     * The ClassLoader for dispatching calls is chosed using the following
+     * rules:
+     * 1) If current thread context ClassLoader is null, then ClassLoader
+     *    which loads Class of remote object will be the ClassLoader for
+     *    dispatching calls
+     * 2) If ClassLoader which loads Class of remote object is null, then
+     *    current thread context ClassLoader will be the ClassLoader for
+     *    dispatching calls
+     * 3) If context ClassLoader of the current thread is equal/parent
+     *    of the ClassLoader which loads Class of remote object, then
+     *    current thread context ClassLoader will be the ClassLoader for for
+     *    dispatching calls.
+     * 4) Otherwise ClassLoader which loads Class of remkote object will
+     *    be the ClassLoader fo dispatching calls.
+     *
+     * @param ref reference to remote object
+     * @param id Object ID for remote object
+     * @param sref UnicastServerRef for dispatching remote calls
+     * @param stub stub for remote object
+     */
+    RMIObjectInfo(RMIReference ref,
+                  ObjID id,
+                  UnicastServerRef sref,
+                  Remote stub) {
+        this.ref = ref;
+        this.id = id;
+        this.sref = sref;
+        this.stub = stub;
+        acc = AccessController.getContext();
+        ClassLoader objCl = ref.get().getClass().getClassLoader();
+        ClassLoader threadCl = Thread.currentThread().getContextClassLoader();
+
+        if (threadCl == null) {
+            loader = objCl;
+        } else if (objCl == null || RMIUtil.isParentLoader(threadCl, objCl)) {
+            loader = threadCl;
+        } else {
+            loader = objCl;
+        }
+    }
+
+    /*
+     * Called by DGC to signal that dirty call received to the object with
+     * such ObjID.
+     */
+    void dgcDirty(VMID vmid, long seqNum, long duration) {
+        synchronized (vmidTable) {
+            DGCExpirationInfo info = (DGCExpirationInfo) vmidTable.get(vmid);
+
+            if (info != null && info.seqNum >= seqNum) {
+                return;
+            }
+            Long l = (Long) rememberedTable.get(vmid);
+
+            if (l != null) {
+                if (l.longValue() > seqNum) {
+                    return;
+                } else {
+                    rememberedTable.remove(vmid);
+                }
+            }
+            ref.makeStrong(true);
+            vmidTable.put(vmid, new DGCExpirationInfo(duration, seqNum));
+        }
+    }
+
+    /*
+     * Called by DGC to signal that clean call received to the object with
+     * such ObjID.
+     */
+    boolean dgcClean(VMID vmid, long seqNum, boolean strong) {
+        synchronized (vmidTable) {
+            DGCExpirationInfo info = (DGCExpirationInfo) vmidTable.get(vmid);
+
+            if (info != null && info.seqNum >= seqNum) {
+                return false;
+            }
+            vmidTable.remove(vmid);
+
+            if (strong) {
+                Long l = (Long) rememberedTable.get(vmid);
+
+                if (l != null && l.longValue() > seqNum) {
+                    return true;
+                }
+                rememberedTable.put(vmid, new Long(seqNum));
+            }
+
+            if (vmidTable.isEmpty()) {
+                unreferenced();
+            }
+            return true;
+        }
+    }
+
+    /*
+     * Called by DGC to verify if the given VMID reference expired.
+     */
+    boolean dgcClean(VMID vmid) {
+        synchronized (vmidTable) {
+            DGCExpirationInfo info = (DGCExpirationInfo) vmidTable.get(vmid);
+
+            if (info != null && info.expTime > System.currentTimeMillis()) {
+                return false;
+            }
+            vmidTable.remove(vmid);
+
+            if (vmidTable.isEmpty()) {
+                unreferenced();
+            }
+            return true;
+        }
+    }
+
+    /*
+     * Spawn thread calling unreferenced() method of the object to be
+     * unreferenced and makes the reference to the object as weak.
+     */
+    private synchronized void unreferenced() {
+        final Object obj = ref.get();
+
+        if (obj instanceof Unreferenced) {
+            /*
+             * Spawn unreferenced thread.
+             * Start this thread with setDaemon(false) to protect VM
+             * from exiting while unreferencing the object.
+             * The thread is started in non-system group
+             * (see comment for CreateThreadAction class).
+             */
+            Thread uThread = ((Thread) AccessController.doPrivileged(
+                    new CreateThreadAction(new Runnable() {
+                        public void run() {
+                            AccessController.doPrivileged(
+                                    new PrivilegedAction() {
+                                        public Object run() {
+                                            ((Unreferenced) obj).unreferenced();
+                                            return null;
+                                        }
+                                    }, acc);
+                        }
+                    }, "Unreferenced", false, false)));
+            uThread.setContextClassLoader(loader);
+            uThread.start();
+        }
+        ref.makeStrong(false);
+    }
+
+
+    /*
+     * Auxiliary class holding expiration time and sequence number when
+     * this expiration was created.
+     */
+    private static class DGCExpirationInfo {
+        // Expiration time in ms.
+        long expTime;
+
+        // Sequence number.
+        long seqNum;
+
+        /*
+         * Constructs an empty DGCExpirationInfo.
+         */
+        DGCExpirationInfo() {
+        }
+
+        /*
+         * Constructs ExpirationInfo class from the given duration and
+         * sequence number.
+         *
+         * @param duration time period after which this entry expires
+         * @param seqNumber Sequence number to handle consecutive calls
+         */
+        DGCExpirationInfo(long duration, long seqNum) {
+            this.expTime = System.currentTimeMillis() + duration;
+            this.seqNum = seqNum;
+        }
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectTable.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectTable.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectTable.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectTable.java Thu May 18 13:01:22 2006
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.util.Hashtable;
+import java.rmi.server.ObjID;
+
+
+/**
+ * Defines structure for storing RMIObjects and methods for finding them by
+ * different separate keys, which are unique inside the table: ObjID and
+ * RMIReference to the object's implementation.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+final class RMIObjectTable {
+
+    // Table where key is ObjID.
+    private Hashtable idTable = new Hashtable();
+
+    // Table where key is RMIReference to the impl.
+    private Hashtable refTable = new Hashtable();
+
+    /*
+     * Object using for synchronization, because we should change
+     * 2 tables simultaneously.
+     */
+    private Object tablesLock = new Object();
+
+    /**
+     * Adds specified info to the table if there are no elements with the
+     * same ObjID or RMIReference to the impl there.
+     *
+     * @param info RMIObjectInfo to be added to the table
+     *
+     * @return true if the table did not contain the given info and the info
+     *         was successfully added to the table and false otherwise
+     *
+     * @throws NullPointerException if info is null or info.id is null
+     */
+    public boolean add(RMIObjectInfo info) {
+        synchronized (tablesLock) {
+            if (!idTable.containsKey(info.id)) {
+                idTable.put(info.id, info);
+                refTable.put(info.ref, info);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the table contains element with specified RMIReference
+     * and false otherwise.
+     *
+     * @param ref RMIReference to the remote object implementation to be used
+     *        as a key
+     *
+     * @return true if the table contains element with specified ref and false
+     *         otherwise
+     */
+    public boolean containsByRef(RMIReference ref) {
+        synchronized (tablesLock) {
+            return refTable.containsKey(ref);
+        }
+    }
+
+    /**
+     * Returns true if the table contains element with specified id and false
+     * otherwise.
+     *
+     * @param id ObjID to be used as a key
+     *
+     * @return true if the table contains element with specified id and false
+     *         otherwise
+     */
+    public boolean containsById(ObjID id) {
+        synchronized (tablesLock) {
+            return idTable.containsKey(id);
+        }
+    }
+
+    /**
+     * Returns true if the table contains element which is equal to the info
+     * specified.
+     *
+     * @param info RMIObjectInfo to be used as a key
+     *
+     * @return true if the table contains element which is equal to the info
+     *         specified
+     */
+    public boolean contains(RMIObjectInfo info) {
+        if (info != null && info.id != null) {
+            synchronized (tablesLock) {
+                return containsById(info.id);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds and returns RMIObjectInfo found by specified reference to remote
+     * object implementation or null if record has not been found.
+     *
+     * @param ref RMIReference to the remote object implementation to be used
+     *        as a key
+     *
+     * @return RMIObjectInfo if found in the table or null if matching record
+     *         has not been found
+     */
+    public RMIObjectInfo getByRef(RMIReference ref) {
+        synchronized (tablesLock) {
+            return (RMIObjectInfo) refTable.get(ref);
+        }
+    }
+
+    /**
+     * Finds and returns RMIObjectInfo found by specified ObjID or null
+     * if record has not been found.
+     *
+     * @param id ObjID to use as a key
+     *
+     * @return RMIObjectInfo if found in the table or null if matching record
+     *         has not been found
+     */
+    public RMIObjectInfo getById(ObjID id) {
+        synchronized (tablesLock) {
+            return (RMIObjectInfo) idTable.get(id);
+        }
+    }
+
+    /**
+     * Removes RMIObjectInfo found by specified reference to remote object
+     * implementation from the table.
+     *
+     * @param ref RMIReference to the remote object implementation to be used
+     *        as a key
+     *
+     * @return RMIObjectInfo if found in the table or null if matching record
+     *         has not been found
+     */
+    public RMIObjectInfo removeByRef(RMIReference ref) {
+        RMIObjectInfo info;
+
+        synchronized (tablesLock) {
+            info = (RMIObjectInfo) refTable.remove(ref);
+
+            if (info != null) {
+                idTable.remove(info.id);
+            }
+        }
+        return info;
+    }
+
+    /**
+     * Removes RMIObjectInfo found by specified ObjID from the table.
+     *
+     * @param id ObjID to use as a key
+     *
+     * @return RMIObjectInfo if found in the table or null if matching record
+     *         has not been found
+     */
+    public RMIObjectInfo removeById(ObjID id) {
+        RMIObjectInfo info;
+
+        synchronized (tablesLock) {
+            info = (RMIObjectInfo) idTable.remove(id);
+
+            if (info != null) {
+                refTable.remove(info.ref);
+            }
+        }
+        return info;
+    }
+
+    /**
+     * Returns true if this table contains no records and false otherwise.
+     *
+     * @return true if this table contains no records and false otherwise
+     */
+    public boolean isEmpty() {
+        synchronized (tablesLock) {
+            return idTable.isEmpty();
+        }
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIObjectTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIReference.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIReference.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIReference.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIReference.java Thu May 18 13:01:22 2006
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import org.apache.harmony.rmi.common.RMILog;
+
+
+/**
+ * Extension of WeakReference. It could contain strong reference to the object.
+ * Also hashCode() and equals() methods are overriden. This class is used for
+ * storing exported rmi objects.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+public class RMIReference extends WeakReference {
+
+    // strong reference to the object this class refers to
+    private Object strongRef = null;
+
+    // Hash code for the referenced object.
+    private int objHashCode;
+
+    /**
+     * Constructs RMIReference from the given Object.
+     */
+    public RMIReference(Object obj) {
+        super(obj);
+        objHashCode = System.identityHashCode(obj);
+    }
+
+    /**
+     * Constructs RMIReference from the given Object and ReferenceQueue.
+     */
+    public RMIReference(Object obj, ReferenceQueue queue) {
+        super(obj, queue);
+        objHashCode = System.identityHashCode(obj);
+    }
+
+    /**
+     * If the given parameter is true then makes this reference strong;
+     * otherwise makes this reference weak.
+     *
+     * @param strong if true then this reference should be made strong
+     */
+    public synchronized void makeStrong(boolean strong) {
+        if (strong) {
+            if (strongRef == null) {
+                strongRef = get();
+
+
+                if (DGCImpl.dgcLog.isLoggable(RMILog.VERBOSE)) {
+                    DGCImpl.dgcLog.log(RMILog.VERBOSE, "Strongly referenced "
+                            + strongRef);
+                }
+            }
+        } else {
+            if (strongRef != null
+                    && DGCImpl.dgcLog.isLoggable(RMILog.VERBOSE)) {
+                DGCImpl.dgcLog.log(RMILog.VERBOSE, "Weakly referenced "
+                        + strongRef);
+            }
+            strongRef = null;
+        }
+    }
+
+    /**
+     * Returns true if the given object is an instance of this class and refer
+     * to the same object as this reference and false otherwise.
+     *
+     * @param obj another object to be compared
+     *
+     * @return true if the given object is an instance of this class and refer
+     *         to the same object as this reference and false otherwise
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof RMIReference)) {
+            return false;
+        }
+        Object refObj = get();
+
+        if (refObj == null) {
+            return false;
+        }
+        return refObj == ((WeakReference) obj).get();
+    }
+
+    /**
+     * Returns hash code for the referenced object.
+     *
+     * @return hash code for the referenced object
+     */
+    public int hashCode() {
+        return objHashCode;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RMIReference.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RemoteRefBase.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RemoteRefBase.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RemoteRefBase.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RemoteRefBase.java Thu May 18 13:01:22 2006
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteRef;
+
+import org.apache.harmony.rmi.transport.Endpoint;
+import org.apache.harmony.rmi.transport.RMIObjectInputStream;
+import org.apache.harmony.rmi.transport.RMIObjectOutputStream;
+
+
+/**
+ * Base class for all RemoteRef implementations.
+ * It belongs to org.apache.harmony.rmi.transport package because it should have
+ * package protected access to ClientDGC implementation.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+public abstract class RemoteRefBase implements RemoteRef {
+
+    private static final long serialVersionUID = 358378173612121423L;
+
+    /** Endpoind this handle refers to. */
+    protected Endpoint ep;
+
+    /** Object ID of remote object. */
+    protected ObjID objId;
+
+    /** True if this handle is for local object. */
+    protected boolean isLocal;
+
+    /**
+     * Returns Object ID for the referenced remote object.
+     *
+     * @return Object ID for the referenced remote object
+     */
+    public ObjID getObjId() {
+        return objId;
+    }
+
+    /**
+     * @see RemoteRef.remoteEquals(RemoteRef)
+     */
+    public boolean remoteEquals(RemoteRef obj) {
+        if (!(obj instanceof RemoteRefBase)) {
+            return false;
+        }
+        RemoteRefBase ref = (RemoteRefBase) obj;
+        return ep.equals(ref.ep) && (objId.equals(ref.objId));
+    }
+
+    /**
+     * @see RemoteRef.remoteToString()
+     */
+    public String remoteToString() {
+        return getRefClass(null) + "[endpoint:[" + ep + "]"
+                + ((isLocal) ? "(local)" : "(remote)") + ", " + objId + "]";
+    }
+
+    /**
+     * Returns the value returned by remoteToString() method.
+     *
+     * @return the value returned by remoteToString() method
+     */
+    public String toString() {
+        return remoteToString();
+    }
+
+    /**
+     * @see RemoteRef.remoteHashCode()
+     */
+    public int remoteHashCode() {
+        return ((objId != null) ? objId.hashCode() : super.hashCode());
+    }
+
+    /**
+     * Reads everything left except Endpoint info from the given stream and
+     * detects if DGC ack is needed.
+     *
+     * @param in the stream to read data from
+     *
+     * @throws IOException if any I/O error occured
+     * @throws ClassNotFoundException if class could not be loaded by current
+     *         class loader
+     */
+    protected void readCommon(ObjectInput in)
+            throws IOException, ClassNotFoundException {
+        objId = ObjID.read(in);
+        boolean needAck = in.readBoolean();
+
+        if (in instanceof RMIObjectInputStream) {
+            RMIObjectInputStream oin = (RMIObjectInputStream) in;
+
+            if (oin.isRemoteCallStream()) {
+                oin.needDGCAck(needAck);
+            }
+        }
+        RMIObjectInfo info = ExportManager.getInfo(objId);
+
+        if ((info == null) || !info.sref.remoteEquals(this)) {
+            /*
+             * This remote object created in another VM so
+             * register it in ClientDGC.
+             */
+            ClientDGC.registerForRenew(this);
+        }
+    }
+
+    /**
+     * Writes everything left except Endpoint info to the given stream.
+     *
+     * @param out the stream to write the object to
+     *
+     * @throws IOException if any I/O error occured or class is not serializable
+     */
+    protected void writeCommon(ObjectOutput out) throws IOException {
+        objId.write(out);
+        boolean isResStream = false;
+
+        if (out instanceof RMIObjectOutputStream) {
+            RMIObjectOutputStream oout = (RMIObjectOutputStream) out;
+            isResStream = oout.isResultStream();
+
+            if (isResStream) {
+                /*
+                 * Because this is a result stream (i.e. obtained in
+                 * RemoteCall.getResultStream() method), after writing all
+                 * objects we will wait for DGC ack call. So, we should register
+                 * this ref for holding a strong reference to the referenced
+                 * remote object.
+                 */
+                ClientDGC.registerForDGCAck(oout.getUID(), this);
+            }
+        }
+        out.writeBoolean(isResStream);
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/RemoteRefBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnection.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnection.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnection.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnection.java Thu May 18 13:01:22 2006
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.rmi.NoSuchObjectException;
+import java.rmi.RemoteException;
+import java.rmi.ServerException;
+import java.rmi.UnmarshalException;
+import java.rmi.server.ObjID;
+import java.rmi.server.UID;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.apache.harmony.rmi.common.RMILog;
+import org.apache.harmony.rmi.common.RMIUtil;
+import org.apache.harmony.rmi.remoteref.UnicastServerRef;
+import org.apache.harmony.rmi.transport.Endpoint;
+import org.apache.harmony.rmi.transport.RMIObjectInputStream;
+import org.apache.harmony.rmi.transport.RMIObjectOutputStream;
+import org.apache.harmony.rmi.transport.RMIProtocolConstants;
+
+
+/**
+ * Connection opened on server side when connection from the client is accepted.
+ * It acknowledges RMI protocol version, RMI protocol type etc. and after that
+ * pass the control to the appropriate UnicastServerRef for processing the
+ * remote call itself.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+public abstract class ServerConnection
+        implements RMIProtocolConstants, Runnable {
+
+    /** Connected socket. */
+    protected Socket s;
+
+    /** InputStream open from the socket. */
+    protected InputStream in;
+
+    /** OutputStream open from the socket. */
+    protected OutputStream out;
+
+    /** Endpoint which this connection connected to. */
+    protected Endpoint ep;
+
+    /** ServerConnectionManager managing this connection. */
+    protected ServerConnectionManager mgr;
+
+    /** Server reference where current remote call is dispatching. */
+    protected UnicastServerRef sref = null;
+
+    /**
+     * Constructs ServerConnection working through socket specified.
+     *
+     * @param s Socket connected to the client
+     * @param mgr ServerConnectionManager managing this connection
+     *
+     * @throws IOException if an I/O error occured during getting
+     *         input/output streams from specified socket
+     */
+    public ServerConnection(Socket s, ServerConnectionManager mgr)
+            throws IOException {
+        this.s = s;
+        this.mgr = mgr;
+        ep = new Endpoint(s.getInetAddress().getHostAddress(),
+                          s.getPort(),
+                          mgr.getEndpoint().getClientSocketFactory(),
+                          mgr.getEndpoint().getServerSocketFactory());
+        out = new BufferedOutputStream(s.getOutputStream());
+        in = new BufferedInputStream(s.getInputStream());
+    }
+
+    /**
+     * Acknowledges RMI protocol version, RMI protocol type etc. and wait for
+     * remote calls from client. After call message dispatch call to apropriate
+     * UnicastServerRef for processing.
+     */
+    public void run() {
+        // sets client host for RemoteServer.getClientHost() method
+        ServerConnectionManager.clientHost.set(
+                s.getInetAddress().getHostAddress());
+
+        try {
+            // acknowledge protocol
+            if (clientProtocolAck() < 0) {
+                return;
+            }
+
+            // wait until RMI call msg is received from client or until client
+            // closes the connection
+            while (waitCallMsg() != -1) {
+                RMIObjectInputStream oin = new RMIObjectInputStream(in);
+                final ServerRemoteCall sCall = new ServerRemoteCall(this, oin);
+                ObjID id = null;
+
+                try {
+                    id = ObjID.read(oin);
+                } catch (IOException ioe) {
+                    throw new UnmarshalException("Unable to read Object ID",
+                            ioe);
+                }
+                RMIObjectInfo info = ExportManager.getInfo(id);
+                RemoteException exToReturn = null;
+
+                if (info == null) {
+                    sref = null;
+                    exToReturn = new NoSuchObjectException(
+                            "No objects with " + id + " exported.");
+                } else {
+                    sref = info.sref;
+
+                    if (!sref.isSystem()) {
+                        mgr.addActiveCall();
+                    }
+
+                    if (ServerConnectionManager.transportLog.isLoggable(
+                            RMILog.VERBOSE)) {
+                        ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
+                                "Dispatch call for processing");
+                    }
+
+                    // Dispatch the call for processing
+                    Thread curThread = Thread.currentThread();
+                    ClassLoader curLoader = curThread.getContextClassLoader();
+                    curThread.setContextClassLoader(info.loader);
+                    final SecurityManager curMgr = System.getSecurityManager();
+
+                    try {
+                        AccessController.doPrivileged(
+                                new PrivilegedExceptionAction() {
+                                    public Object run() throws IOException {
+                                        /*
+                                         * First check if we can accept
+                                         * the calls from the given endpoint.
+                                         */
+                                        if (curMgr != null) {
+                                            curMgr.checkAccept(ep.getHost(),
+                                                    ep.getPort());
+                                        }
+                                        sref.processCall(sCall);
+                                        return null;
+                                    }
+                                }, info.acc);
+                    } catch (PrivilegedActionException pae) {
+                        IOException ioe = (IOException) pae.getException();
+
+                        if (ioe instanceof RemoteException) {
+                            exToReturn = new ServerException(
+                                    "RemoteException occurred in server thread",
+                                    ioe);
+                        } else {
+                            throw ioe;
+                        }
+                    } finally {
+                        curThread.setContextClassLoader(curLoader);
+                    }
+                }
+
+                if (exToReturn != null) {
+                    sCall.releaseInputStream();
+                    if (ServerConnectionManager.transportLog.isLoggable(
+                            RMILog.VERBOSE)) {
+                        ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
+                                "Return exception to the client: "
+                                + exToReturn);
+                    }
+                    DataOutputStream dout = new DataOutputStream(out);
+                    RMIObjectOutputStream oout;
+
+                    if (sCall.hasResultStream()) {
+                        oout = (RMIObjectOutputStream)
+                                sCall.getOutputStream();
+                    } else {
+                        oout = (RMIObjectOutputStream)
+                                sCall.getResultStream(false);
+                    }
+                    oout.writeObject(exToReturn);
+                    oout.flush();
+                }
+
+                if (sref != null) {
+                    if (!sref.isSystem()) {
+                        mgr.removeActiveCall();
+                    }
+                    sref = null;
+                }
+                releaseOutputStream();
+            }
+        } catch (IOException ioe) {
+            //ioe.printStackTrace(System.err);
+        } finally {
+            if (sref != null) {
+                if (!sref.isSystem()) {
+                    mgr.removeActiveCall();
+                }
+                sref = null;
+            }
+
+            // stop this thread, close the socket and remove this connection
+            // from the list of active connections in ConnectionManager
+            mgr.stopConnection(this);
+        }
+    }
+
+    /**
+     * Acknowledges protocol with client side.
+     *
+     * @return acknowledged protocol number
+     *
+     * @throws RemoteException if any I/O exception occured during protocol
+     *         acknowledgement
+     */
+    protected abstract int clientProtocolAck() throws IOException;
+
+    /**
+     * Waiting until 0x50 code (CALL_MSG) message will be received (this code
+     * will be returned as a result of this method call). If the
+     * connection with the client is closed while waiting for this code, -1
+     * should be returned.
+     *
+     * @return 0x50 code if this code is received from the client or -1 if
+     *         the socket was closed while waiting for CALL_MSG code
+     *
+     * @throws IOException if any I/O error occured while communicating with
+     *         client
+     */
+    protected abstract int waitCallMsg() throws IOException;
+
+    /**
+     * This method should be called when DGC_ACK response was received.
+     * It unregisters the given UID in ClientDGC.
+     *
+     * @param uid UID DGC_ACK response for which was read
+     */
+    protected void dgcUnregisterUID(UID uid) {
+        ClientDGC.unregisterForDGCAck(uid);
+    }
+
+    /**
+     * Closes this connection.
+     */
+    public void close() {
+        try {
+            s.close();
+        } catch (IOException e) {
+            if (ServerConnectionManager.transportLog.isLoggable(
+                    RMILog.VERBOSE)) {
+                ServerConnectionManager.transportLog.log(RMILog.VERBOSE,
+                        "Note: close operation produced exception: ", e);
+            }
+        }
+    }
+
+    /**
+     * Returns true if this connection is handling remote call and false
+     * otherwise.
+     *
+     * @return true if this connection is handling remote call and false
+     *         otherwise
+     */
+    public boolean hasActiveCall() {
+        return sref != null;
+    }
+
+    /**
+     * By default does nothing.
+     */
+    public void releaseInputStream() throws IOException {
+    }
+
+    /**
+     * By default does nothing.
+     */
+    public void releaseOutputStream() throws IOException {
+    }
+
+    /**
+     * Returns open input stream.
+     *
+     * @return open input stream
+     */
+    public InputStream getInputStream() {
+        return in;
+    }
+
+    /**
+     * Returns open output stream.
+     *
+     * @return open output stream
+     */
+    public OutputStream getOutputStream() {
+        return out;
+    }
+
+    /**
+     * Returns string representation of this connection.
+     *
+     * @return string representation of this connection
+     */
+    public String toString() {
+        return RMIUtil.getShortName(getClass()) + ": remote endpoint:" + ep;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnectionManager.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnectionManager.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnectionManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnectionManager.java Thu May 18 13:01:22 2006
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.server.RMIFailureHandler;
+import java.rmi.server.RMISocketFactory;
+import java.security.AccessController;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import org.apache.harmony.rmi.common.CreateThreadAction;
+import org.apache.harmony.rmi.common.RMILog;
+import org.apache.harmony.rmi.transport.Endpoint;
+import org.apache.harmony.rmi.transport.proxy.HttpInboundSocket;
+import org.apache.harmony.rmi.transport.proxy.HttpServerConnection;
+import org.apache.harmony.rmi.transport.tcp.TcpServerConnection;
+
+
+/**
+ * Manager waiting for client connections and initiating communication with
+ * them.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+public class ServerConnectionManager implements Runnable {
+
+    // Client host for RemoteServer.getClientHost() method
+    static ThreadLocal clientHost = new ThreadLocal();
+
+    /*
+     * Table of local endpoints (keys) and appropriate mapped connection
+     * manager (values).
+     */
+    private static Hashtable localEps = new Hashtable();
+
+    // ServerSocket where this manager waits for connections
+    private ServerSocket ss;
+
+    // Local Endpoint for this connection
+    private Endpoint ep;
+
+    // List of accepted(active) connections
+    private Set conns = Collections.synchronizedSet(new HashSet());
+
+
+    // Number of in-progress calls to the objects in this table.
+    private int activeCallsNum = 0;
+
+    // lock object for working with active calls
+    private Object callsLock = new Object();
+
+    /*
+     * Default wait time after 5 consecutive failed accept attempts
+     * if RMIFailureHandler is not set.
+     */
+    private static final long defaultFailureDelay = 3000;
+
+    // Number of failed accepts attempts.
+    private long failedAcceptsNum = 0;
+
+    // Log for logging transport-layer activity
+    static final RMILog transportLog = RMILog.getTransportLog();
+
+    /**
+     * Constructs ServerConnectionManager and creates ServerSocket.
+     *
+     * @param sref server-side handle for exported remote object
+     *
+     * @throws IOException if any I/O error occured during opening ServerSocket
+     */
+    private ServerConnectionManager(Endpoint localEp)
+            throws IOException {
+        ep = localEp;
+        ss = ep.createServerSocket();
+    }
+
+    /**
+     * Returns ServerConnectionManager corresponding to the given ep. If such a
+     * manager does not exist creates it and put record to the table.
+     *
+     * @param ep Endpoint to get ServerConnectionManager for
+     *
+     * @return found (created) ServerConnectionManager
+     *
+     * @throws IOException and and I/O error occured during manager creation
+     */
+    public static synchronized ServerConnectionManager getMgr(Endpoint ep)
+            throws IOException {
+        ServerConnectionManager mgr;
+        Endpoint tmpl = null;
+
+        if (ep.getPort() != 0) {
+            tmpl = Endpoint.createTemplate(ep);
+            mgr = (ServerConnectionManager) localEps.get(tmpl);
+
+            if (mgr != null) {
+                // verify that we can listen on the Endpoint's port
+                SecurityManager sm = System.getSecurityManager();
+
+                if (sm != null) {
+                    sm.checkListen(ep.getPort());
+                }
+                return mgr;
+            }
+        }
+        mgr = new ServerConnectionManager(ep);
+        ((Thread) AccessController.doPrivileged(
+                new CreateThreadAction(mgr, "ServerConnectionManager["
+                        + mgr.getEndpoint() + "]", true))).start();
+        if (tmpl == null) {
+            tmpl = Endpoint.createTemplate(ep);
+        }
+        localEps.put(tmpl, mgr);
+        return mgr;
+    }
+
+    /**
+     * Returns the string representation of the client's host for RMI calls
+     * which are processed in the current thread (this method is intended to be
+     * called by RemoteServer.getClientHost() method).
+     *
+     * @return string representation of the client's host for RMI calls which
+     *         are processed in the current thread
+     */
+    public static String getClientHost() {
+        return (String) clientHost.get();
+    }
+
+    /**
+     * Returns true if there are in-progress calls to remote objects
+     * associated with this manager.
+     *
+     * @return true if there are in-progress calls to remote object
+     *         associated with this manager
+     */
+    public boolean hasActiveCalls() {
+        synchronized (callsLock) {
+            return (activeCallsNum != 0);
+        }
+    }
+
+    /**
+     * Returns server's endpoint.
+     *
+     * @return server's endpoint;
+     */
+    public Endpoint getEndpoint() {
+        return ep;
+    }
+
+    /**
+     * Starts waiting for incoming remote calls. When connection from remote
+     * is accepted, separate thread to process remote call is spawned. Waits
+     * for connections until this thread will not be interrupted.
+     */
+    public void run() {
+        while (!Thread.interrupted()) {
+            try {
+                Socket s = ss.accept();
+                startConnection(s);
+                failedAcceptsNum = 0;
+            } catch (Exception ex) {
+                RMIFailureHandler rfh = RMISocketFactory.getFailureHandler();
+
+                if (rfh != null) {
+                    if (rfh.failure(ex)) {
+                        return;
+                    }
+                } else {
+                    // We will try to immediately accept another client again,
+                    // but if we have a bad client wich fails our accept tries
+                    // for a number of times, we should sleep for a while.
+                    if (failedAcceptsNum >= 5) {
+                        try {
+                            Thread.sleep(defaultFailureDelay);
+                        } catch (InterruptedException ie) {
+                            return;
+                        }
+                        failedAcceptsNum = 0;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Stops specified connection with remote client: closes opened Socket,
+     * stops appropriate thread and removes this connection from the list of
+     * active connections.
+     *
+     * @param conn connection to be stopped
+     */
+    public void stopConnection(ServerConnection conn) {
+        conn.close();
+        conns.remove(conn);
+    }
+
+    /**
+     * Increase the number of active calls by one.
+     */
+    protected void addActiveCall() {
+        synchronized (callsLock) {
+            ++activeCallsNum;
+            ExportManager.addActiveCall();
+        }
+    }
+
+    /**
+     * Decrease the number of active callse by one.
+     */
+    protected void removeActiveCall() {
+        synchronized (callsLock) {
+            --activeCallsNum;
+            ExportManager.removeActiveCall();
+        }
+    }
+
+    /*
+     * Starts separate thread communicating with remote client to process
+     * remote call.
+     *
+     * @param s Socket connected with remote client
+     *
+     * @return connection to the remote client
+     *
+     * @throws IOException if any I/O error occured while starting connection
+     */
+    private ServerConnection startConnection(Socket s)
+            throws IOException {
+        ServerConnection conn;
+
+        if (s instanceof HttpInboundSocket) {
+            conn = new HttpServerConnection(s, this);
+        } else {
+            conn = new TcpServerConnection(s, this);
+        }
+        conns.add(conn);
+
+        /*
+         * Start the thread in non-system group
+         * (see comment for CreateThreadAction class).
+         */
+        Thread connThread = (Thread) AccessController.doPrivileged(
+                new CreateThreadAction(conn, "Call from " + conn.ep, true,
+                        false));
+        connThread.start();
+
+        if (transportLog.isLoggable(RMILog.VERBOSE)) {
+            transportLog.log(RMILog.VERBOSE, "Accepted " + conn);
+        }
+        return conn;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerConnectionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerRemoteCall.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerRemoteCall.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerRemoteCall.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerRemoteCall.java Thu May 18 13:01:22 2006
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.server;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.StreamCorruptedException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.rmi.server.RemoteCall;
+
+import org.apache.harmony.rmi.transport.RMIObjectInputStream;
+import org.apache.harmony.rmi.transport.RMIObjectOutputStream;
+import org.apache.harmony.rmi.transport.RMIProtocolConstants;
+
+
+/**
+ * RemoteCall implementation used by UnicastServerRef on server's side.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.2 $
+ */
+public class ServerRemoteCall implements RemoteCall, RMIProtocolConstants {
+
+    // Connection to remote server.
+    private ServerConnection conn;
+
+    // InputStream for reading objects.
+    private ObjectInputStream oin = null;
+
+    // OutputStream for sending objects.
+    private RMIObjectOutputStream oout = null;
+
+    // True if getResultStream has been called.
+    private boolean hasResStream = false;
+
+    /**
+     * Constructs ServerRemoteCall from existing connection.
+     *
+     * @param conn opened ServerConnection
+     */
+    public ServerRemoteCall(ServerConnection conn) {
+        this.conn = conn;
+    }
+    /**
+     * Constructs ServerRemoteCall from opened connection and already created
+     * ObjectOutputStream.
+     *
+     * @param conn opened ServerConnection
+     * @param oin created ObjectOutputStream
+     */
+    public ServerRemoteCall(ServerConnection conn, ObjectInputStream oin) {
+        this.conn = conn;
+        this.oin = oin;
+    }
+
+    /**
+     * Constructs ObjectInputStream (if it was not created yet) and returns
+     * this created stream.
+     *
+     * @return ObjectInputStream to read objects from
+     *
+     * @throws IOException if an I/O error occured during stream construction
+     */
+    public ObjectInput getInputStream() throws IOException {
+        if (oin == null) {
+            oin = new RMIObjectInputStream(conn.getInputStream());
+        }
+        return oin;
+    }
+
+    /**
+     * Constructs ObjectOutputStream (if it was not created yet) and returns
+     * this created stream.
+     *
+     * @return ObjectOutputStream to write objects to
+     *
+     * @throws IOException if an I/O error occured during stream construction
+     */
+
+    public ObjectOutput getOutputStream() throws IOException {
+        if (oout == null) {
+            oout = new RMIObjectOutputStream(conn.getOutputStream());
+        }
+        return oout;
+    }
+
+    /**
+     * Writes byte meaning normal call return, writes byte identifying call
+     * result (normal return or exception) - depending on success parameter,
+     * writes UID of the object (for DGC) and flushes the output stream.
+     * This method could be called only once.
+     *
+     * @param success if true - means that method call was successfull (i.e.
+     *        with no exception) - return data description will be written to
+     *        the output stream
+     *
+     * @throws IOexception if an I/O error occured while writing to the stream
+     * @throws StreamCorruptedException if this method has already been called
+     */
+    public ObjectOutput getResultStream(boolean success)
+            throws IOException, StreamCorruptedException {
+        if (hasResStream) {
+            throw new StreamCorruptedException(
+                    "getResultStream() method has already been called.");
+        }
+        (new DataOutputStream(conn.getOutputStream())).writeByte(CALL_OK);
+
+        if (oout == null) {
+            oout = new RMIObjectOutputStream(conn.getOutputStream(), true);
+        }
+        oout.writeByte(success ? RETURN_VAL : RETURN_EX);
+        oout.writeUID();
+        oout.flush();
+        hasResStream = true;
+        return oout;
+    }
+
+    /**
+     * @see RemoteCall.releaseInputStream()
+     */
+    public void releaseInputStream() throws IOException {
+        conn.releaseInputStream();
+    }
+
+    /**
+     * @see RemoteCall.releaseOutputStream()
+     */
+    public void releaseOutputStream() throws IOException {
+    }
+
+    /**
+     * @see RemoteCall.done()
+     */
+    public void done() throws IOException {
+        conn.close();
+    }
+
+    /**
+     * Not used on server side.
+     */
+    public void executeCall() throws Exception {
+    }
+
+    /**
+     * Returns string representation of this RemoteCall.
+     *
+     * @return string representation of this RemoteCall
+     */
+    public String toString() {
+        return "ServerRemoteCall: connection: " + conn;
+    }
+
+    /**
+     * Returns true if getResultStream was already called before and
+     * false otherwise.
+     *
+     * @return true if getResultStream was already called before and
+     *         false otherwise
+     */
+    public boolean hasResultStream() {
+        return hasResStream;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/ServerRemoteCall.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/package.html
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/package.html?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/package.html (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/package.html Thu May 18 13:01:22 2006
@@ -0,0 +1,25 @@
+<html>
+<!--
+Copyright 2005-2006 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.
+-->
+<!--
+Author:  Vasily Zakharov
+Version: $Revision: 1.1.2.1 $
+-->
+<body>
+RMI server side implementation classes.
+</body>
+</html>

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/server/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/DefaultRMISocketFactory.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/DefaultRMISocketFactory.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/DefaultRMISocketFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/DefaultRMISocketFactory.java Thu May 18 13:01:22 2006
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov, Vasily Zakharov
+ * @version $Revision: 1.1.2.2 $
+ */
+package org.apache.harmony.rmi.transport;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.NoRouteToHostException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.security.AccessController;
+
+import org.apache.harmony.rmi.common.GetBooleanPropAction;
+import org.apache.harmony.rmi.common.GetLongPropAction;
+import org.apache.harmony.rmi.common.RMILog;
+import org.apache.harmony.rmi.common.RMIProperties;
+import org.apache.harmony.rmi.transport.proxy.HttpProxyRMISocketFactory;
+import org.apache.harmony.rmi.transport.proxy.Proxy;
+import org.apache.harmony.rmi.transport.proxy.ProxyRMISocketFactory;
+import org.apache.harmony.rmi.transport.tcp.DirectRMISocketFactory;
+
+
+/**
+ * Default {@link RMISocketFactory} which is used by RMI runtime to create
+ * client and server sockets. First it tries direct sockets and if
+ * the attempt fails it tries HTTP-through sockets.
+ *
+ * @author  Mikhail A. Markov, Vasily Zakharov
+ * @version $Revision: 1.1.2.2 $
+ */
+public class DefaultRMISocketFactory extends RMISocketFactory
+        implements Serializable, RMIProperties {
+
+    /**
+     * serialVersionUID
+     */
+    private static final long serialVersionUID = 8559677966812417163L;
+
+    // Should we disable direct socket connections or not.
+    private static final boolean disableDirectSocket =
+            ((Boolean) AccessController.doPrivileged(
+                    new GetBooleanPropAction(DISABLE_DIRECT_SOCKET_PROP)))
+                            .booleanValue();
+
+    // Should we disable HTTP tunneling or not.
+    private static final boolean disableHttp =
+            ((Boolean) AccessController.doPrivileged(
+                    new GetBooleanPropAction(DISABLEHTTP_PROP)))
+                            .booleanValue();
+
+    // Should we try HTTP connections after every SocketException or not.
+    private static final boolean eagerHttpFallback =
+            ((Boolean) AccessController.doPrivileged(
+                    new GetBooleanPropAction(EAGERHTTPFALLBACK_PROP)))
+                            .booleanValue();
+
+    // Direct sockets factory.
+    private static final DirectRMISocketFactory directRsf =
+                                                new DirectRMISocketFactory();
+
+    // Proxy sockets factory.
+    private static final ProxyRMISocketFactory proxyRsf =
+                                                new HttpProxyRMISocketFactory();
+
+    /*
+     * Max period of time (in ms) for trying direct connections before
+     * attempting HTTP. Default value is 15000 ms (15 sec.).
+     */
+    private static long connTimeout = ((Long) AccessController.doPrivileged(
+            new GetLongPropAction(CONNECTTIMEOUT_PROP, 15000))).longValue();
+
+    // Log for logging proxy connections activity.
+    private static final RMILog proxyTransportLog =
+            RMILog.getProxyTransportLog();
+
+    /**
+     * {@inheritDoc}
+     */
+    public Socket createSocket(String host, int port) throws IOException {
+        if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+            proxyTransportLog.log(RMILog.BRIEF,
+                    "Creating socket to [" + host + ':' + port + "].");
+        }
+        Socket s = null;
+        Proxy proxy = new Proxy();
+
+        if (disableDirectSocket) {
+            // If direct connections are disabled, fallback to proxy connection.
+            if (proxyTransportLog.isLoggable(RMILog.VERBOSE)) {
+                proxyTransportLog.log(RMILog.VERBOSE,
+                        "Direct socket connections disabled, "
+                        + "trying proxy connection to ["
+                        + host + ':' + port + "].");
+            }
+        } else {
+            if (disableHttp || !(proxy.isSet())) {
+                // If HTTP is not available, use simple direct connection.
+                s = directRsf.createSocket(host, port);
+
+                if (s == null) {
+                    String msg = "Unable to connect to [" + host + ':' + port
+                            + ']';
+                    if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+                        proxyTransportLog.log(RMILog.BRIEF, msg);
+                    }
+                    throw new NoRouteToHostException(msg);
+                }
+            } else { // Both direct and HTTP connections are available.
+                s = null;
+                IOException ex = null;
+
+                try {
+                    s = directRsf.createSocket(host, port, (int) connTimeout);
+                } catch (IOException ioe) {
+                    ex = ioe;
+                }
+
+                if (s == null) {
+                    // Direct socket attempt failed.
+                    if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+                        proxyTransportLog.log(RMILog.BRIEF,
+                                "Direct socket connection to ["
+                                + host + ':' + port + "] failed.");
+                    }
+
+                    if (ex != null) {
+                        if ((eagerHttpFallback
+                                && !(ex instanceof SocketException))
+                                || (!eagerHttpFallback
+                                    && !(ex instanceof UnknownHostException)
+                                    && !(ex instanceof NoRouteToHostException))) {
+                            throw ex;
+                        } else {
+                            if (proxyTransportLog.isLoggable(RMILog.VERBOSE)) {
+                                proxyTransportLog.log(RMILog.VERBOSE,
+                                        "Trying proxy connection to ["
+                                        + host + ':' + port + "].");
+                            } // Falling through to HTTP connection attempt.
+                        }
+                    } else {
+                        throw new NoRouteToHostException("Connection "
+                                + "to [" + host + ':' + port + "] timed out");
+                    }
+                } else if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+                    proxyTransportLog.log(RMILog.BRIEF,
+                            "Direct socket connection to [" + host + ':' + port
+                            + "] from port " + s.getLocalPort()+ " succeeded.");
+                }
+            }
+        }
+
+        // Either disableDirectSocket or fallback from direct connection attempt.
+        if (s == null) {
+            s = proxyRsf.createSocket(proxy, host, port);
+
+            if (s == null) {
+                String msg = "Proxy connection to [" + host + ':' + port
+                        + "] failed";
+                if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+                    proxyTransportLog.log(RMILog.BRIEF, msg);
+                }
+
+                throw new NoRouteToHostException(msg);
+            }
+
+            if (proxyTransportLog.isLoggable(RMILog.BRIEF)) {
+                proxyTransportLog.log(RMILog.BRIEF,
+                        "Proxy connection to [" + host + ':' + port
+                        + "] from port " + s.getLocalPort()+ " succeeded.");
+            }
+        }
+        return s;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ServerSocket createServerSocket(int port) throws IOException {
+        return ((!disableDirectSocket && disableHttp)
+                ? (RMISocketFactory) directRsf : proxyRsf).createServerSocket(
+                        port);
+    }
+
+    /**
+     * Helper method: returns non-null RMIClientSocketFactory.
+     * Returns specified RMIClientSocketFactory if it is not null; otherwise
+     * returns result of getSocketFactory method call if it is not null;
+     * ottherwise returns result of getDefaultSocketFactory method call.
+     *
+     * @param csf RMIClientSocketFactory to check
+     *
+     * @return non-null RMIClientSocketFactory
+     */
+    public static RMIClientSocketFactory getNonNullClientFactory(
+            RMIClientSocketFactory csf) {
+        RMIClientSocketFactory factory =
+                (csf == null) ? getSocketFactory() : csf;
+        return (factory == null) ? getDefaultSocketFactory() : factory;
+    }
+
+    /**
+     * Helper method: returns non-null RMIServerSocketFactory.
+     * Returns specified RMIServerSocketFactory if it is not null; otherwise
+     * returns result of getSocketFactory method call if it is not null;
+     * ottherwise returns result of getDefaultSocketFactory method call.
+     *
+     * @param ssf RMIServerSocketFactory to check
+     *
+     * @return non-null RMIServerSocketFactory
+     */
+     public static RMIServerSocketFactory getNonNullServerFactory(
+            RMIServerSocketFactory ssf) {
+        RMIServerSocketFactory factory =
+                (ssf == null) ? getSocketFactory() : ssf;
+        return (factory == null) ? getDefaultSocketFactory() : factory;
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/DefaultRMISocketFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/Endpoint.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/Endpoint.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/Endpoint.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/Endpoint.java Thu May 18 13:01:22 2006
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2005-2006 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.
+ */
+
+/**
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+package org.apache.harmony.rmi.transport;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.rmi.ConnectIOException;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.security.AccessController;
+
+import org.apache.harmony.rmi.common.CreateThreadAction;
+import org.apache.harmony.rmi.common.GetBooleanPropAction;
+import org.apache.harmony.rmi.common.GetLongPropAction;
+import org.apache.harmony.rmi.common.GetStringPropAction;
+import org.apache.harmony.rmi.common.RMIProperties;
+
+
+/**
+ * Endpoint implementation: it contains information about host, port,
+ * client-side and server-side socket factories.
+ *
+ * @author  Mikhail A. Markov
+ * @version $Revision: 1.1.2.3 $
+ */
+public class Endpoint {
+
+    /** Indicates null client-side factory. */
+    public static final int NULL_CSF = 0x00;
+
+    /** Indicates non-null client-side factory. */
+    public static final int NONNULL_CSF = 0x01;
+
+    // Host address.
+    private final String host;
+
+    // Port number.
+    private int port;
+
+    // Client-side socket factory.
+    private RMIClientSocketFactory csf;
+
+    // Server-side socket factory.
+    private RMIServerSocketFactory ssf;
+
+    // Local host address.
+    private static String localHost = getLocalHost();
+
+    // True if local host has been obtained and is not equal to 127.0.0.1
+    private static boolean isLocalHostIdentified = false;
+
+    // If non-null then it'll be used as a result of getLocalHost() method call.
+    private static String localHostPropVal =
+            (String) AccessController.doPrivileged(new GetStringPropAction(
+                    RMIProperties.HOSTNAME_PROP));
+
+    // If true then we will forcibly use FQDN by default.
+    private static boolean useLocalHostName =
+            ((Boolean) AccessController.doPrivileged(new GetBooleanPropAction(
+                    RMIProperties.USELOCALHOSTNAME_PROP))).booleanValue();
+
+    /*
+     * The time that we will wait to obtain FQDN for this local host (in ms).
+     * The default value is 10000 ms (10 sec.).
+     */
+    private static int localHostNameTimeout =
+            ((Long) AccessController.doPrivileged(
+                new GetLongPropAction(RMIProperties.LOCALHOSTNAMETIMEOUT_PROP,
+                        10000))).intValue();
+
+    /**
+     * Constructs Local Endpoint.
+     *
+     * @param port port number
+     * @param csf client-side socket factory
+     * @param ssf server-side socket factory
+     */
+    public Endpoint(int port,
+                    RMIClientSocketFactory csf,
+                    RMIServerSocketFactory ssf) {
+        host = getLocalHost();
+        this.port = port;
+        this.csf = csf;
+        this.ssf = ssf;
+    }
+
+    /**
+     * Constructs Endpoint.
+     *
+     * @param host host address/name
+     * @param port port number
+     * @param csf client-side socket factory
+     * @param ssf server-side socket factory
+     */
+    public Endpoint(String host,
+                    int port,
+                    RMIClientSocketFactory csf,
+                    RMIServerSocketFactory ssf) {
+        this.host = host;
+        this.port = port;
+        this.csf = csf;
+        this.ssf = ssf;
+    }
+
+    /**
+     * Returns Endpoint created from the given Endpoint but having null host
+     * (Such Endpoints are used for local endpoints for comparison).
+     *
+     * @param ep Endpoint to create template from
+     *
+     * @return created Endpoint
+     */
+    public static Endpoint createTemplate(Endpoint ep) {
+        return new Endpoint(null, ep.port, ep.csf, ep.ssf);
+    }
+
+    /**
+     * Creates and returns server socket.
+     *
+     * @return created server socket
+     */
+    public ServerSocket createServerSocket() throws IOException {
+        ServerSocket ss = DefaultRMISocketFactory.getNonNullServerFactory(ssf)
+                .createServerSocket(port);
+
+        if (port == 0) {
+            port = ss.getLocalPort();
+        }
+        return ss;
+    }
+
+    /**
+     * Creates and returns socket.
+     *
+     * @return created socket
+     */
+    public Socket createSocket() throws RemoteException {
+        Socket s;
+
+        try {
+            s = DefaultRMISocketFactory.getNonNullClientFactory(csf)
+                    .createSocket(host, port);
+        } catch (java.net.UnknownHostException uhe) {
+            throw new java.rmi.UnknownHostException(
+                    "Unable to connect to server " + toString(), uhe);
+        } catch (java.net.ConnectException ce) {
+            throw new java.rmi.ConnectException(
+                    "Unable to connect to server " + toString(), ce);
+        } catch (IOException ioe) {
+            throw new ConnectIOException(
+                    "Unable to connect to server " + toString(), ioe);
+        }
+        return s;
+    }
+
+    /**
+     * Returns client-side socket factory of this endpoint.
+     *
+     * @return client-side socket factory of this endpoint
+     */
+    public RMIClientSocketFactory getClientSocketFactory() {
+        return csf;
+    }
+
+    /**
+     * Returns server-side socket factory of this endpoint.
+     *
+     * @return server-side socket factory of this endpoint
+     */
+    public RMIServerSocketFactory getServerSocketFactory() {
+        return ssf;
+    }
+
+    /**
+     * Returns the port of this endpoint.
+     *
+     * @return the port of this endpoint
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * Returns the host address of this endpoint.
+     *
+     * @return the host address of this endpoint
+     */
+    public String getHost() {
+        return host;
+    }
+
+    /**
+     * Compares this Endpoint with another object. Returns true if the given
+     * object is an instance of TcpEndpoint and has the same host, port, csf and
+     * ssf fields.
+     *
+     * @return true if objects are equal and false otherwise
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof Endpoint)) {
+            return false;
+        }
+        Endpoint anotherEp = (Endpoint) obj;
+
+
+        if (port != anotherEp.port) {
+            return false;
+        }
+
+        if ((host == null) ? (host != anotherEp.host)
+                : !host.equals(anotherEp.host)) {
+            return false;
+        }
+
+        if ((csf == null) ? (csf != anotherEp.csf)
+                : !csf.equals(anotherEp.csf)) {
+            return false;
+        }
+
+        if ((ssf == null) ? (ssf != anotherEp.ssf)
+                : !ssf.equals(anotherEp.ssf)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns hashCode for this Endpoint.
+     *
+     * @return hashCode for this Endpoint
+     */
+    public int hashCode() {
+        return port;
+    }
+
+    /**
+     * Writes this Endpoint to the given ObjectOutput.
+     *
+     * @param out ObjectOutput to write this Endpoint to
+     * @param writeCsf do we need to write client-side factory or not
+     *
+     * @throws IOException if any I/O error occured during writing
+     */
+    public void writeExternal(ObjectOutput out, boolean writeCsf)
+            throws IOException {
+        if (writeCsf) {
+            if (csf == null) {
+                out.writeByte(NULL_CSF);
+            } else {
+                out.writeByte(NONNULL_CSF);
+            }
+        }
+        out.writeUTF(host);
+        out.writeInt(port);
+
+        if (writeCsf && csf != null) {
+            out.writeObject(csf);
+        }
+    }
+
+    /**
+     * Reads data for creating Endpoint object from the specified input stream.
+     *
+     * @param in the stream to read data from
+     * @param readCsf do we need to read client-side factory or not
+     *
+     * @return created Endpoint
+     *
+     * @throws IOException if any I/O error occured
+     * @throws ClassNotFoundException if class could not be loaded by current
+     *         class loader
+     */
+    public static Endpoint readExternal(ObjectInput in, boolean readCsf)
+            throws IOException, ClassNotFoundException {
+        int inCsf = NULL_CSF;
+
+        if (readCsf) {
+            inCsf = in.readUnsignedByte();
+        }
+        String host = (String) in.readUTF();
+        int port = in.readInt();
+        RMIClientSocketFactory csf = null;
+
+        if (readCsf && inCsf == NONNULL_CSF) {
+            csf = (RMIClientSocketFactory) in.readObject();
+        }
+        return new Endpoint(host, port, csf, null);
+    }
+
+    /**
+     * Returns string representation of this Endpoint.
+     *
+     * @return string representation of this Endpoint
+     */
+    public String toString() {
+        String str = "[" + host + ":" + port;
+
+        if (csf != null) {
+            str += ", csf: " + csf;
+        }
+
+        if (ssf != null) {
+            str += ", ssf: " + ssf;
+        }
+        return str  + "]";
+    }
+
+    /*
+     * Returns local host. If local host was already obtained, then return it
+     * as a result. Otherwise perform the following steps:
+     * 1) Reads java.rmi.server.hostname property if it is not equal to zero
+     *    then returns it's value
+     * 2) Obtains local host by calling InetAddress.getLocalHost()
+     * 3) If java.rmi.server.useLocalHostname property is set to true then tries
+     *    to obtain FQDN (fully qualified domain name) for hostname obtained
+     *    in step 2 and returns it as a result.
+     * 4) If property above is not set (or set to false) then returns the result
+     *    of InetAddress.getLocalHost().getHostAddress() method call.
+     *
+     * @return local host
+     */
+    private static synchronized String getLocalHost() {
+        if (isLocalHostIdentified) {
+            return localHost;
+        }
+        if (localHostPropVal != null) {
+            isLocalHostIdentified = true;
+            localHost = localHostPropVal;
+            return localHost;
+        }
+
+        try {
+            InetAddress iaddr = InetAddress.getLocalHost();
+            byte[] addr = iaddr.getAddress();
+
+            if (useLocalHostName) {
+                localHost = getFQDN(iaddr);
+            } else {
+                localHost = iaddr.getHostAddress();
+            }
+            isLocalHostIdentified = true;
+        } catch (Exception ex) {
+            localHost = null;
+        }
+        return localHost;
+    }
+
+    /*
+     * Returns Fully Qualified Domain Name (FQDN) for the specified InetAddress.
+     * It'll try to obtain this name no longer then the time specified
+     * in harmony.rmi.transport.tcp.localHostNameTimeOut property.
+     *
+     * @param iaddr InetAddress to obtain FQDN
+     *
+     * @return obtained FQDN for the given InetAddress
+     */
+    private static String getFQDN(InetAddress iaddr)
+            throws UnknownHostException {
+        String hostName = iaddr.getHostName();
+
+        if (hostName.indexOf('.') >= 0) {
+            // contains dots (so we think that it is a FQDN already)
+            return hostName;
+        }
+
+        // does not contain dots, so we presume that getHostName()
+        // did not return fqdn
+        String addr = iaddr.getHostAddress();
+        FQDNGetter getter = new FQDNGetter(addr);
+        Thread fqdnThread = (Thread) AccessController.doPrivileged(
+                new CreateThreadAction(getter, "FQDN getter.", true));
+
+        try {
+            synchronized (getter) {
+                fqdnThread.start();
+                getter.wait(localHostNameTimeout);
+            }
+        } catch (InterruptedException ie) {
+        }
+        String fqdn = getter.getFQDN();
+
+        if (fqdn == null || fqdn.indexOf('.') < 0) {
+            return addr;
+        }
+        return fqdn;
+    }
+
+
+    /*
+     * Obtains Fully Qualified Domain Name.
+     */
+    private static class FQDNGetter implements Runnable {
+        private String addr;
+        private String name;
+
+        FQDNGetter(String addr) {
+            this.addr = addr;
+        }
+
+        public void run() {
+            try {
+                name = InetAddress.getByName(addr).getHostName();
+            } catch (UnknownHostException uhe) {
+            } finally {
+                synchronized (this) {
+                    notify();
+                }
+            }
+        }
+
+        private String getFQDN() {
+            return name;
+        }
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/transport/Endpoint.java
------------------------------------------------------------------------------
    svn:eol-style = native