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 [15/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/transport/MultiThreadedServer.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/MultiThreadedServer.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/MultiThreadedServer.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/MultiThreadedServer.java Tue May 16 06:51:00 2006
@@ -0,0 +1,365 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.server.ExportException;
+import java.rmi.server.RMIFailureHandler;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * Implements a {@link ThreadPoolExecutor} that executes each submitted task using one
+ * of possibly several pooled threads. The {@link ThreadPoolExecutor} uses a
+ * {@link BlockingQueue} to transfer and hold submitted tasks.
+ * <p>
+ * <li>The pool size is configured through the property <EM>ar.org.fitc.rmi.server.threadPoolCoreSize</EM>,
+ * the default value is <EM>10</EM>.
+ * <li>The maximum pool size is configured through the property <EM>ar.org.fitc.rmi.server.threadPoolMaxSize</EM>,
+ * the default value is <EM>Integer.MAX_VALUE</EM>.
+ * <li>The keep alive time of the thread waiting in the pool is configured
+ * through the property <EM>ar.org.fitc.rmi.server.threadPoolKeepAliveTime</EM> ,
+ * the default value is <EM>60000</EM> in milliseconds.
+ * <li>Finally, the capacity of the queue is configured through the property
+ * <EM>ar.org.fitc.rmi.server.threadPoolQueueSize</EM>, the default value is
+ * <EM>0</EM>.
+ *
+ * <p>
+ * This class has an internal class:
+ * {@link ar.org.fitc.rmi.transport.MultiThreadedServer.ServerRequestTask}
+ *
+ * @author Marcelo Arcidiacono
+ * @author Gustavo Petri
+ */
+final class MultiThreadedServer extends Thread {
+
+ /**
+ * The blocking queue which is used to transfer and hold submitted tasks.
+ */
+ private static BlockingQueue<Runnable> queue;
+
+ /**
+ * The thread pool that executes each submitted task.
+ */
+ private static ThreadPoolExecutor threadPool = null;
+
+ static {
+ Integer poolSize;
+ Integer maxPoolSize;
+ Long keepAliveTime;
+ Integer queueCapacity;
+
+ poolSize = PropertiesReader.readInt(
+ "ar.org.fitc.rmi.server.threadPoolCoreSize", 10);
+
+ maxPoolSize = PropertiesReader.readInt(
+ "ar.org.fitc.rmi.server.threadPoolMaxSize", Integer.MAX_VALUE);
+
+ keepAliveTime = PropertiesReader.readLong(
+ "ar.org.fitc.rmi.server.threadPoolKeepAliveTime", 60000);
+
+ queueCapacity = PropertiesReader.readInt(
+ "ar.org.fitc.rmi.server.threadPoolQueueSize", 0);
+
+ queue = (queueCapacity == 0) ? new SynchronousQueue<Runnable>()
+ : new ArrayBlockingQueue<Runnable>(queueCapacity);
+
+ threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,
+ keepAliveTime, TimeUnit.MILLISECONDS, queue,
+ new SimpleThreadFactory());
+ threadPool.prestartAllCoreThreads();
+ }
+
+ /**
+ * Indicates if the serverSocket will not accept any incoming call, the
+ * default value is <code>true</code>.
+ */
+ private volatile boolean notFinish;
+
+ /**
+ * The specified port number.
+ */
+ private int port;
+
+ /**
+ * The server socket that waits for requests.
+ */
+ private ServerSocket serverSocket;
+
+ /**
+ * Associated with a remote object to obtain the
+ * {@link java.net.ServerSocket} which is used to accept incoming calls from
+ * clients.
+ */
+ private RMIServerSocketFactory ssf;
+
+ /**
+ * Constructor for the {@link MultiThreadedServer}. In order to
+ * guarantee serial access creates a synchronized (thread-safe) map backed
+ * by the specified map.
+ *
+ * @param ssf
+ * the specified {@link java.rmi.server.RMIServerSocketFactory}
+ * @param port
+ * the specified number of port
+ * @throws ExportException
+ * if the exportation is not successful
+ */
+ public MultiThreadedServer(RMIServerSocketFactory ssf, int port)
+ throws ExportException {
+ this.ssf = ssf;
+ this.port = port;
+ try {
+ this.serverSocket = createServerSocket();
+ } catch (IOException e) {
+ throw new ExportException("Exception happened during exportation",
+ e);
+ }
+ this.setName("MultiThreadedServer" + serverSocket);
+ this.notFinish = true;
+ }
+
+ /**
+ * Executes a task on one of the several pooled threads.
+ *
+ * @param client
+ * the client socket
+ * @param clientEP
+ * the {@link ar.org.fitc.rmi.transport.EndpointID} associated to
+ * client
+ * @throws IOException
+ * if the connection failed
+ */
+ private final void serverRequests(Socket client, EndpointID clientEP)
+ throws IOException {
+ AbstractServerConnection server = ServerConnectionFactory
+ .getServerConnection(client.getInputStream(),
+ client.getOutputStream(), clientEP, client);
+ threadPool.execute(new ServerRequestTask(client, server));
+ }
+
+ /**
+ * Implements the retrial of reconnections when a failure occurs in the
+ * {@link ServerSocket#accept()} method
+ *
+ * @see <a href="http://archives.java.sun.com/cgi-bin/wa?A2=ind9909&L=rmi-users&D=0&I=-3&P=22293">User Archives</a>
+ * @param acceptException
+ * the exception which was thrown when the accept method failed
+ */
+ private final void handleServerSocketFailure(IOException acceptException) {
+ RMIFailureHandler fh = RMISocketFactory.getFailureHandler();
+ if (fh == null) {
+ // There isn't any FailureHandler installed. Retry 10 times every 10
+ // seconds.
+ int retry = 0;
+ while (retry < 10 && notFinish) {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ }
+ try {
+ serverSocket = createServerSocket();
+ break;
+ } catch (IOException e) {
+ retry++;
+ }
+ }
+ if (retry >= 10) {
+ notFinish = false;
+ }
+ } else {
+ // There is a FailureHandler installed. Ask to FailureHandler for
+ // retries.
+ boolean retry = fh.failure(acceptException);
+ while (retry && notFinish) {
+ try {
+ serverSocket = createServerSocket();
+ break;
+ } catch (IOException createSocketException) {
+ retry = fh.failure(createSocketException);
+ }
+ }
+ if (!retry) {
+ notFinish = false;
+ }
+ }
+ }
+
+ /**
+ * Creates a {@link java.net.ServerSocket}.
+ *
+ * @return a {@link java.net.ServerSocket}
+ * @throws IOException
+ * if the creation fails
+ */
+ private final ServerSocket createServerSocket() throws IOException {
+ ServerSocket serverSocket;
+ RMISocketFactory socketFactory;
+ if (ssf == null) {
+ socketFactory = RMISocketFactory.getSocketFactory();
+ if (socketFactory == null) {
+ socketFactory = RMISocketFactory.getDefaultSocketFactory();
+ }
+ serverSocket = socketFactory.createServerSocket(port);
+ } else {
+ serverSocket = ssf.createServerSocket(port);
+ }
+ return serverSocket;
+ }
+
+ /**
+ * Returns the local port number of the {@link java.net.ServerSocket}.
+ *
+ * @return the local port number of the {@link java.net.ServerSocket}
+ */
+ public final int getLocalPort() {
+ return serverSocket.getLocalPort();
+ }
+
+ /**
+ * Listens for a connection to be made to this socket and accepts it. The
+ * method blocks until a connection is made.
+ *
+ * @see <a
+ * href="http://archives.java.sun.com/cgi-bin/wa?A2=ind9909&L=rmi-users&D=0&I=-3&P=22293">User Archives</a>
+ */
+ @Override
+ public void run() {
+ Socket newClient;
+ while (notFinish) {
+ try {
+ newClient = serverSocket.accept();
+ // FIXME Make a private setSocketProperties method
+ newClient.setTcpNoDelay(true);
+ EndpointID clientEndpointID = new EndpointID(newClient
+ .getInetAddress().getHostAddress(), newClient.getPort());
+ try {
+ serverRequests(newClient, clientEndpointID);
+ } catch (IOException e) {
+ if (notFinish) {
+ /*
+ * Any recovering acction should be done here if needed
+ * be.
+ */
+ }
+ }
+ } catch (IOException acceptException) {
+ if (notFinish) {
+ // serversocket.accept() has failed. Ask RMIFailureHandler
+ // for retries.
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ }
+ handleServerSocketFailure(acceptException);
+ }
+ }
+ }
+ }
+
+ /**
+ * Close the {@link java.net.ServerSocket}.
+ *
+ * @throws IOException
+ * if the {@link java.net.ServerSocket} cannot to close
+ */
+ public final void stopServing() throws IOException {
+ this.serverSocket.close();
+ this.notFinish = false;
+ }
+
+ /**
+ * Defines the task submitted in the Thread Pool
+ *
+ * @author Marcelo Arcidiacono
+ * @author Gustavo Petri
+ */
+ private final class ServerRequestTask implements Runnable {
+
+ /**
+ * The client socket
+ */
+ private Socket client;
+
+ /**
+ * The server connection.SO_REUSEADDR
+ */
+ private AbstractServerConnection server;
+
+ /**
+ * Constructor for the {@link ServerRequestTask}
+ *
+ * @param client
+ * the especified client socket
+ * @param server
+ * the especified server connection
+ */
+ public ServerRequestTask(Socket client, AbstractServerConnection server) {
+ this.client = client;
+ this.server = server;
+ }
+
+ /**
+ * Serves a connection
+ */
+ public final void run() {
+ Map<Long, Pair<String, Integer>> clientConnectionMap =
+ TransportManager.getTransportManager().getClientConnectionMap();
+ clientConnectionMap.put(Thread.currentThread().getId(),
+ new Pair<String, Integer>(client.getInetAddress()
+ .getHostAddress(), new Integer(server.getConnectionID())));
+ try {
+ server.establishConnection();
+ while (true) {
+ server.serve();
+ }
+ } catch (Exception e) {
+ server.releaseConnection();
+ server = null;
+ // FIXME REVIEW: May be some logging would be useful here.
+ // Also any recovery action should be called here.
+ }
+ }
+ }
+
+}
+
+/**
+ * A factory of a simple thread
+ *
+ * @author Marcelo Arcidiacono
+ * @author Gustavo Petri
+ */
+final class SimpleThreadFactory implements ThreadFactory {
+
+ public final Thread newThread(Runnable r) {
+ Thread thread = new Thread(r);
+ thread.setDaemon(true);
+ return thread;
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/MultiThreadedServer.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ProtocolException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ProtocolException.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ProtocolException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ProtocolException.java Tue May 16 06:51:00 2006
@@ -0,0 +1,61 @@
+/*
+* 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.transport;
+
+import java.rmi.RemoteException;
+
+/**
+ * @author Gustavo Petri
+ */
+public class ProtocolException extends RemoteException {
+
+ /**
+ * Serial number 1L
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor of <code>ProtocolException</code>
+ */
+ public ProtocolException() {
+ super();
+ }
+
+ /**
+ * Constructor of <code>ProtocolException</code>, receives a <code>
+ * String</code>
+ *
+ * @param message
+ * message of the <code>ProtocolException</code>
+ */
+ public ProtocolException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor of <code>ProtocolException</code>, receives a <code>
+ * String</code>
+ * and <code>Throwable</code>
+ *
+ * @param message
+ * message of the <code>ProtocolException</code>
+ * @param cause
+ * that it has generated this exception
+ */
+ public ProtocolException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ProtocolException.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIDefaultSocketFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIDefaultSocketFactory.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIDefaultSocketFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIDefaultSocketFactory.java Tue May 16 06:51:00 2006
@@ -0,0 +1,353 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.NoRouteToHostException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.rmi.server.RMISocketFactory;
+import java.util.HashMap;
+import java.util.Map;
+
+import ar.org.fitc.rmi.transport.http.HttpSocketClientSide;
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * This is the default {@link java.rmi.server.RMISocketFactory} used by the RMI
+ * Runtime.
+ *
+ * @author Gustavo Petri
+ * @author Diego Raúl Mercado
+ */
+public final class RMIDefaultSocketFactory extends RMISocketFactory {
+
+ /**
+ * Is true if the system's property <code>java.rmi.server.disableHttp</code>
+ * and <code>http.proxyHost</code> are true.
+ */
+ private static boolean enableHttp;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>ar.org.fitc.rmi.transport.proxy.leaseTime</code>. <br>
+ * Indicates the maximum value to wait until trying again the fallback
+ * mechanism.
+ */
+ private static long leaseTime;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>ar.org.fitc.rmi.transport.proxy.eagerHttpFallback</code>. <br>
+ * If the <code>java.rmi.server.disableHttp</code> is false and this
+ * property is set to true then would try http tunneling if a
+ * <code>SocketException</code> ocurrs
+ */
+ private static boolean eagerHttpFallback;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>http.proxyHost</code>. <br>
+ * Represents the IP or address name of the host that act as a proxy. Will
+ * be used to forward the remote call invocation
+ */
+ private static String proxyHost;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>http.proxyPort</code>. <br>
+ * Represents the port of the host that act as a proxy. The default value is
+ * 80. Will be used to forward the remote call invocation
+ */
+ private static int proxyPort;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>ar.org.fitc.rmi.transport.proxy.connectTimeout</code>. <br>
+ * Sets the maximum time (in milliseconds) that the runtime will wait for a
+ * direct connection attempt to establish, before trying http tunneling.
+ * It's used only if <code>java.rmi.server.disableHttp</code> is false and
+ * <code>http.proxyHost</code> is set.
+ */
+ private static int connectTimeout;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>ar.org.fitc.rmi.transport.proxy.httpToPortOnly</code>. <br>
+ * Setting this value to true will only try to establish a connection
+ * through the proxy that was specified in <code>http.proxyHost</code>.
+ * <br>
+ * This avoid the default fallback mechanism.
+ */
+ private static boolean proxyOnly;
+
+ /**
+ * Indicates the value returned by the system's property
+ * <code>ar.org.fitc.rmi.transport.proxy.httpToCgiOnly</code>. <br>
+ * Setting this value to true will only try to establish a connection
+ * through the proxy that was specified in <code>http.proxyHost</code> and
+ * execute the cgi's script at the web server. <br>
+ * This avoid the default fallback mechanism.
+ */
+ private static boolean cgiOnly;
+
+ /**
+ * For each host and port stores the FallBackType and the last time that a
+ * socket has been created for that parameters.
+ */
+ private static Map<Pair<String, Integer>, Pair<FallBackType, Long>> connType;
+
+ static {
+
+ /*
+ * READING PROPERTIES
+ */
+
+ leaseTime = PropertiesReader.readLong(
+ "ar.org.fitc.rmi.transport.proxy.leaseTime", 3600000L); // 1
+ // hour
+
+ connectTimeout = PropertiesReader.readInt(
+ "ar.org.fitc.rmi.transport.proxy.connectTimeout", 15000);
+
+ proxyHost = PropertiesReader.readString("http.proxyHost");
+
+ proxyPort = PropertiesReader.readInt("http.proxyPort", 80);
+
+ eagerHttpFallback = PropertiesReader.readBoolean(
+ "ar.org.fitc.rmi.transport.proxy.eagerHttpFallback", false);
+
+ proxyOnly = PropertiesReader.readBoolean(
+ "ar.org.fitc.rmi.transport.proxy.httpToPortOnly", false);
+
+ cgiOnly = PropertiesReader.readBoolean(
+ "ar.org.fitc.rmi.transport.proxy.httpToCgiOnly", false);
+
+ boolean disableHttp = PropertiesReader.readBoolean(
+ "java.rmi.server.disableHttp", false);
+
+ enableHttp = proxyHost != null && !disableHttp;
+
+ connType = new HashMap<Pair<String, Integer>, Pair<FallBackType, Long>>();
+ }
+
+ /**
+ * Create a socket through a three-tiered approach: first, attempt to create
+ * a default
+ * {@link Socket} with the specified host and port. <br>
+ * If that fails, <code>java.rmi.server.disableHttp</code> is enabled and
+ * <code>http.proxyHost</code> property is set, attempt to create a
+ * {@link HttpSocketClientSide} with the specified
+ * <code>http.proxyHost</code> and <code>http.proxyPort</code>. That
+ * is, specifying the folowing url:
+ * <code>http://<host>:<port></code> <br>
+ * Finally, attempts to invoke a cgi-script on the specified proxy with the
+ * following url:
+ * <code>http://<host>:80/cgi-bin/java-rmi?forward=<port></code>
+ *
+ * @param host
+ * the host to connect the socket
+ * @param port
+ * the port to connect the socket
+ * @return a new {@link Socket} instance connected to the host and
+ * port specified
+ * @throws IOException
+ * if de I/O operation fails
+ */
+ @Override
+ public final Socket createSocket(String host, int port) throws IOException {
+ Pair<Socket, FallBackType> sockPair = null;
+ Pair<String, Integer> inetAddr = new Pair<String, Integer>(host, port);
+
+ // is there a reference ?
+ Pair<FallBackType, Long> fallBackPair = connType.get(inetAddr);
+ if (fallBackPair != null) {
+ if (fallBackPair.getSecond() < System.currentTimeMillis()
+ - leaseTime) {
+ // the lease time has expired do the fallback ...
+ sockPair = fallBack(host, port);
+ } else {
+ try {
+ sockPair = new Pair<Socket, FallBackType>(connect(
+ fallBackPair.getFirst(), host, port), fallBackPair
+ .getFirst());
+ } catch (IOException e) {
+ // do the fallback...
+ sockPair = fallBack(host, port);
+ }
+ }
+ } else {
+ // do the fallback...
+ sockPair = fallBack(host, port);
+ }
+ // put / update reference
+ connType.put(inetAddr, new Pair<FallBackType, Long>(sockPair
+ .getSecond(), System.currentTimeMillis()));
+
+ return sockPair.getFirst();
+ }
+
+ /**
+ * Creates a new {@link RMIServerSocket} bound to the specified port.
+ *
+ * @param port
+ * the port to bind the server
+ * @return a new {@link RMIServerSocket} bound to the specified port.
+ * @throws IOException
+ * if de I/O operation fails
+ */
+ @Override
+ public final ServerSocket createServerSocket(int port) throws IOException {
+ return new RMIServerSocket(port);
+ }
+
+ /**
+ * Implements the fallback logic, which will attempt all connection types
+ * until one success.
+ *
+ * @param host
+ * The host name of the RMI Server
+ * @param port
+ * The port of the RMI Server
+ * @return A {@link Pair} object containing a {@link Socket} bound
+ * to the appropriate server, and the {@link FallBackType}
+ * object representing the approach used to establish the connection.
+ * @throws IOException
+ * If all connection types have failed.
+ */
+ private final Pair<Socket, FallBackType> fallBack(String host, int port)
+ throws IOException {
+ FallBackType fbType = null;
+ IOException returnedException = null;
+ Socket newSock = null;
+ boolean isEstablished = false;
+ boolean notFallback = proxyOnly || cgiOnly;
+
+ try {
+ if (enableHttp && notFallback) {
+ if (proxyOnly) {
+ newSock = connect(FallBackType.PROXY, host, port);
+ fbType = FallBackType.PROXY;
+ } else if (cgiOnly) {
+ newSock = connect(FallBackType.PROXY_CGI, host, port);
+ fbType = FallBackType.PROXY_CGI;
+ }
+ } else {
+ // DIRECT CONNECTION
+ newSock = connect(FallBackType.DIRECT, host, port);
+ fbType = FallBackType.DIRECT;
+ }
+ isEstablished = true;
+ } catch (UnknownHostException e) {
+ returnedException = e;
+ } catch (NoRouteToHostException e) {
+ returnedException = e;
+ } catch (SocketTimeoutException e) {
+ // this property has to be set and is catched
+ // when newSock tries to connect with a "connectTimeout"
+ returnedException = e;
+ } catch (SocketException e) {
+ // if disableHttp property has not been set (checks this value in
+ // the next if block) and eagerHttpFallback is true...
+ if (!(eagerHttpFallback)) {
+ throw e;
+ }
+ returnedException = e;
+ }
+
+ // HTTP
+ if (!isEstablished && enableHttp && !notFallback) {
+ // PROXY_HOST ON PROXY_PORT USING HTTP
+ try {
+ newSock = connect(FallBackType.PROXY, host, port);
+ fbType = FallBackType.PROXY;
+ isEstablished = true;
+ } catch (NoRouteToHostException e) {
+ returnedException = e;
+ } catch (UnknownHostException e) {
+ returnedException = e;
+ }
+
+ if (!isEstablished) {
+ // PROXY_CGI ON RMI SERVER ON PORT 80 USING HTTP
+ newSock = connect(FallBackType.PROXY_CGI, host, port);
+ fbType = FallBackType.PROXY_CGI;
+ isEstablished = true;
+ }
+ }
+
+ if (!isEstablished) {
+ throw returnedException;
+ }
+ return new Pair<Socket, FallBackType>(newSock, fbType);
+ }
+
+ /**
+ * Attempts a connection to the appropriate server, depending on the
+ * specified {@link FallBackType} parameter.
+ *
+ * @param fallBackType
+ * The type of connection (Direct, HTTPProxy, HTTPCGI) that will
+ * be used.
+ * @param host
+ * The host name of the RMI Server
+ * @param port
+ * The port of the RMI Server
+ * @return A {@link Socket} bound to the appropriate server.
+ * @throws IOException
+ * If the connection attempt for the specified
+ * {@link FallBackType} has failed.
+ */
+ private final Socket connect(FallBackType fallBackType, String host,
+ int port) throws IOException {
+ Socket newSock = null;
+ if (fallBackType.equals(FallBackType.DIRECT)) {
+
+ // DIRECT CONNECTION with TimeOut
+ if (enableHttp) {
+ newSock = new Socket();
+ newSock.connect(new InetSocketAddress(host, port),
+ connectTimeout);
+ } else {
+ // DIRECT CONNECTION
+ newSock = new Socket();
+ newSock.connect(new InetSocketAddress(host, port));
+ }
+ } else if (fallBackType.equals(FallBackType.PROXY)) {
+
+ // PROXY_HOST ON PROXY_PORT USING HTTP
+ newSock = new HttpSocketClientSide(new URL("http", proxyHost,
+ proxyPort, "http://" + host + ":" + port + "/"));
+
+ } else if (fallBackType.equals(FallBackType.PROXY_CGI)) {
+
+ // PROXY_CGI ON RMI SERVER ON PORT 80 USING HTTP
+ newSock = new HttpSocketClientSide(new URL("http", proxyHost,
+ proxyPort, "http://" + host
+ + ":80/cgi-bin/java-rmi.cgi?forward=" + port));
+
+ } else {
+ throw new AssertionError();
+ }
+ return newSock;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIDefaultSocketFactory.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectInputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectInputStream.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectInputStream.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectInputStream.java Tue May 16 06:51:00 2006
@@ -0,0 +1,166 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.rmi.Remote;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.rmi.server.RemoteStub;
+
+import ar.org.fitc.rmi.dgc.client.DGCClient;
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.PropertiesReader;
+
+/**
+ * This class is used by the RMI Runtime to serialize and deserialize Remote
+ * Objects. For that purpose the {@link #resolveClass} and
+ * {@link #resolveProxyClass} methods have been overloaded.
+ *
+ * @author Gustavo Petri
+ * @author Gonzalo Ortega
+ */
+public final class RMIObjectInputStream extends ObjectInputStream {
+
+ private static boolean useCodebaseOnly =
+ PropertiesReader.readBoolean("java.rmi.server.useCodebaseOnly", false);
+
+ private boolean readsRemote;
+
+ /**
+ * Delegates the creation of an ObjectInputStream to its parent class.
+ *
+ * @throws IOException
+ * if I/O operation fails
+ */
+ public RMIObjectInputStream() throws IOException {
+ super();
+ enableResolveObject(true);
+ }
+
+ /**
+ * Delegates the creation of an ObjectInputStream to its parent class.
+ *
+ * @param in
+ * the
+ * {@link InputStream}
+ * to which this instance will be attached.
+ * @throws IOException
+ * if de I/O operation fails
+ */
+ public RMIObjectInputStream(InputStream in) throws IOException {
+ super(in);
+ enableResolveObject(true);
+ }
+
+ /**
+ * Returns a pair (object-boolean) from the read object.
+ *
+ * @return a pair (object-boolean) from the read object
+ * @throws IOException
+ * if de I/O operation fails
+ * @throws ClassNotFoundException
+ * if no definition for the class with the specified name could
+ * be found
+ */
+ public synchronized final Pair<Object, Boolean> readResultObject()
+ throws IOException, ClassNotFoundException {
+ readsRemote = false;
+ Object obj = this.readObject();
+ return new Pair<Object, Boolean>(obj, new Boolean(readsRemote));
+ }
+
+ /**
+ * Returns the Class that corresponds to the desc argument.
+ *
+ * @param desc
+ * the descriptor of the needed Class
+ * @return the Class for the desc descriptor
+ */
+ @SuppressWarnings("deprecation")
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc)
+ throws IOException, ClassNotFoundException {
+ Class<?> ret = null;
+ Object obj = this.readObject();
+ try {
+ ret = Class.forName(desc.getName(), true, Thread.currentThread()
+ .getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ if ((obj != null && obj instanceof String) && (!useCodebaseOnly)) {
+ ret = RMIClassLoader.loadClass((String) obj, desc.getName());
+ } else {
+ ret = RMIClassLoader.loadClass(desc.getName());
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Constructs and returns a Proxy class that implements the required
+ * interfaces.
+ *
+ * @param interfaces
+ * the interfaces to be implemented
+ * @return a proxy class that implements the specified interfaces
+ * @throws IOException
+ * if de I/O operation fails
+ */
+ @Override
+ protected Class<?> resolveProxyClass(String[] interfaces)
+ throws IOException, ClassNotFoundException {
+ Object obj = this.readObject();
+ try {
+ return super.resolveProxyClass(interfaces);
+ } catch (Exception e) {
+ return RMIClassLoader
+ .loadProxyClass((String) obj, interfaces, null);
+ }
+ }
+
+ /**
+ * Transforms a locally exported Remote Object to its corresponding stub in *
+ * for the serialization proces.
+ *
+ * @param obj
+ * the specified Object
+ */
+ @Override
+ protected Object resolveObject(Object obj) throws IOException {
+ if (obj instanceof Remote) {
+ if (obj instanceof RemoteStub) {
+ DGCClient dgcClient = DGCClient.getDGCClient();
+ readsRemote = true;
+ return dgcClient.getStubInstance((RemoteStub) obj);
+ }
+ if (Proxy.isProxyClass(obj.getClass())) {
+ InvocationHandler ih = Proxy
+ .getInvocationHandler(obj);
+ if (ih instanceof RemoteObjectInvocationHandler) {
+ DGCClient dgcClient = DGCClient.getDGCClient();
+ readsRemote = true;
+ return dgcClient.getStubInstance((Remote) obj);
+ }
+ }
+ }
+ return obj;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectInputStream.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectOutputStream.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectOutputStream.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectOutputStream.java Tue May 16 06:51:00 2006
@@ -0,0 +1,166 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.rmi.Remote;
+import java.rmi.server.RMIClassLoader;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.rmi.server.RemoteStub;
+import ar.org.fitc.rmi.runtime.RemoteReferenceManager;
+
+/**
+ * This class is used by the RMI Runtime to serialize and deserialize Remote
+ * Objects. For that purpose the {@link #replaceObject}, {@link #annotateClass}
+ * and {@link #annotateProxyClass} methods have been overloaded.
+ *
+ * @author Gustavo Petri
+ */
+
+public final class RMIObjectOutputStream extends ObjectOutputStream {
+
+ /**
+ * This set holds the {@link java.rmi.server.UID} for which a DGCAck is
+ * still pending.
+ */
+ private boolean writesRemote;
+
+ /**
+ * Delegates the creation of an ObjectInputStream to its parent class.
+ *
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ protected RMIObjectOutputStream() throws IOException {
+ super();
+ enableReplaceObject(true);
+ }
+
+ /**
+ * Delegates the creation of an ObjectInputStream to its parent class.
+ *
+ * @param out
+ * The
+ * {@link OutputStream}
+ * from which the new {@link RMIObjectOutputStream} will be created
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ public RMIObjectOutputStream(OutputStream out) throws IOException {
+
+ super(out);
+// flush();
+ enableReplaceObject(true);
+ }
+
+ /**
+ * Writes an object and returns true if and only if a
+ * {@link java.rmi.Remote} object has been writtenRMIObjectOutputStream
+ *
+ * @param obj
+ * the specified Object
+ * @return true if a {@link java.rmi.Remote} object has been written to the
+ * {@link ObjectOutputStream}
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ public synchronized final boolean writeResultObject(Object obj)
+ throws IOException {
+
+ writesRemote = false;
+ this.writeObject(obj);
+ return writesRemote;
+ }
+
+ /**
+ * Returns a stub if the object to be serialized is a
+ * {@link java.rmi.Remote} instance.
+ *
+ * @param obj
+ * the object to be replaced if needed be.
+ * @return if the argument was a {@link java.rmi.Remote} object locally
+ * exported a stub for that object is returned, in case it is not a
+ * {@link java.rmi.Remote} the object is returned
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ @Override
+ protected final Object replaceObject(Object obj) throws IOException {
+
+ if (obj instanceof Remote) {
+ RemoteReferenceManager rrm = RemoteReferenceManager
+ .getRemoteReferenceManager();
+ if (rrm.isExported((Remote) obj)) {
+ writesRemote = true;
+ return RemoteObject.toStub((Remote) obj);
+ }
+ if (obj instanceof RemoteStub) {
+ writesRemote = true;
+ return obj;
+ }
+ if (Proxy.isProxyClass(obj.getClass())) {
+ InvocationHandler ih = Proxy.getInvocationHandler(obj);
+ if (ih instanceof RemoteObjectInvocationHandler) {
+ writesRemote = true;
+ }
+ }
+ }
+ return obj;
+ }
+
+ /**
+ * Writes the annotation for the class passed as argument on the
+ * {@link RMIObjectOutputStream}
+ *
+ * @param cl
+ * the class to be annotated
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ @Override
+ protected final void annotateClass(Class<?> cl) throws IOException {
+ Object obj = RMIClassLoader.getClassAnnotation(cl);
+ this.writeObject(obj);
+ }
+
+ /**
+ * Writes the annotation for the Proxy class passed as argument on the
+ * RMIOutputStream.
+ *
+ * @param cl
+ * the class to be annotated
+ * @throws IOException
+ * if the I/O operation fails
+ */
+ @Override
+ protected final void annotateProxyClass(Class<?> cl) throws IOException {
+ Object obj = RMIClassLoader.getClassAnnotation(cl);
+ this.writeObject(obj);
+ }
+
+ /**
+ * Writes the pending content to the underlying stream.
+ */
+ @Override
+ public final void drain() throws IOException {
+ super.drain();
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIObjectOutputStream.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIServerSocket.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIServerSocket.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIServerSocket.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIServerSocket.java Tue May 16 06:51:00 2006
@@ -0,0 +1,81 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import ar.org.fitc.rmi.transport.http.HttpSocketServerSide;
+import ar.org.fitc.rmi.transport.jrmp.ProtocolHeader;
+
+/**
+ * The purpose of this class is to be aware of the socket that has to be
+ * returned in the {@link #accept()} method. Because of that, it has to
+ * read the first 4 bytes of the socket's input stream returned by the
+ * {@link java.net.ServerSocket#accept()} method of the superclass
+ *
+ * @author Diego Raúl Mercado
+ */
+final class RMIServerSocket extends ServerSocket {
+
+ /**
+ * Constructor. Before establishing the connection set the socket's address
+ * as reusable
+ *
+ * @param port
+ * the port of this serverSocket
+ * @throws IOException
+ * if an I/O error occurs when creating this serverSocket
+ */
+ public RMIServerSocket(int port) throws IOException {
+ super();
+ super.bind(new InetSocketAddress(port));
+ }
+
+ /**
+ * @ar.org.fitc.spec_ref
+ * Read the first 4 bytes of the socket's input stream returned at the
+ * {@link java.net.ServerSocket#accept()} method of the superclass. Then,
+ * determine which socket has to be returned or throw an IOException if
+ * cannot recognize the stream
+ */
+ @Override
+ public final Socket accept() throws IOException {
+ Socket sock;
+ InputStream in;
+ byte[] protocol = new byte[4];
+ ProtocolHeader protHeader;
+
+ sock = super.accept();
+ in = sock.getInputStream();
+
+ for (int i = 0; i < 4; i++) {
+ protocol[i] = (byte)in.read();
+ }
+ protHeader = ProtocolHeader.createProtocolHeader(protocol);
+ if (protHeader.equals(ProtocolHeader.JRMI_PROTOCOL_HEADER)) {
+ return sock;
+ } else if (protHeader.equals(ProtocolHeader.HTTP_PROTOCOL_HEADER)) {
+ return new HttpSocketServerSide(sock);
+ } else {
+ //TODO LOG
+ throw new IOException("Unrecognized Header Protocol");
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/RMIServerSocket.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ServerConnectionFactory.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ServerConnectionFactory.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ServerConnectionFactory.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ServerConnectionFactory.java Tue May 16 06:51:00 2006
@@ -0,0 +1,52 @@
+/*
+* 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.transport;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+import ar.org.fitc.rmi.transport.http.HttpSocketServerSide;
+
+/**
+ * Factory for Server Connections.
+ * @author Gustavo Petri
+ */
+public final class ServerConnectionFactory {
+
+ /** Prevents instantiation */
+ private ServerConnectionFactory() {}
+
+ /**
+ * Creates a Connection acording to the type of the {@link Socket} argument
+ * @param in the {@link InputStream} for the Connection to be created
+ * @param out the {@link OutputStream} for the Connection to be created
+ * @param clientEP the {@link Endpoint} of the client for this Connection
+ * @param sock the {@link Socket} for this connection
+ * @return a Connection to serve client requests
+ */
+ public final static AbstractServerConnection getServerConnection(InputStream in,
+ OutputStream out, EndpointID clientEP, Socket sock) {
+ AbstractServerConnection ret;
+
+ if (sock instanceof HttpSocketServerSide) {
+ ret = new SingleOpServerConnection(in, out, clientEP, sock);
+ } else {
+ ret = new StreamServerConnection(in, out, clientEP, sock);
+ }
+ return ret;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/ServerConnectionFactory.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpClientConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpClientConnection.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpClientConnection.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpClientConnection.java Tue May 16 06:51:00 2006
@@ -0,0 +1,116 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.rmi.ConnectIOException;
+import java.rmi.MarshalException;
+import java.rmi.server.ObjID;
+import java.rmi.server.UID;
+
+import ar.org.fitc.rmi.transport.jrmp.ProtocolType;
+import ar.org.fitc.rmi.transport.jrmp.ReturnMessage;
+
+/**
+ * Encapsulates the Client events occurring in the JRMP protocol, when is
+ * encapsulated inside an HTTP call. It creates a socket for the specified
+ * {@link ar.org.fitc.rmi.transport.Endpoint}, it sends all
+ * the parameters in the apropriate order and it waits for the results.
+ *
+ * @author Gustavo Petri
+ */
+final class SingleOpClientConnection extends AbstractClientConnection {
+
+ /**
+ * Creates a new connection to the specified
+ * {@link ar.org.fitc.rmi.transport.Endpoint}.
+ * @param sock
+ * the {@link Socket} to be used by this Connection
+ * @param ep
+ * the {@link ar.org.fitc.rmi.transport.Endpoint} to connect
+ * @throws ConnectIOException
+ * if an IOException occurs while making a connection to the
+ * remote host
+ */
+ public SingleOpClientConnection(Socket sock, Endpoint ep) throws ConnectIOException {
+ super(sock, ep);
+ }
+
+ /**
+ * Establishes a connection.
+ * <li>If {@link #lastUsageTime} is <code>null</code> then starts a
+ * connection.
+ * <li>If the difference between current time and {@link #lastUsageTime} is
+ * bigger or equal than double of the value stored in the table then renew
+ * the connection. The multiplied constant 2 is suggested in this
+ * {@link <a href="http://archives.java.sun.com/cgi-bin/wa?A2=ind0101&L=rmi-users&P=R23746&D=0&I=-3">link</a>}
+ *
+ * @throws MarshalException
+ * if a {@link java.io.IOException} occurs while marshalling the
+ * remote call header, arguments or return value for a remote
+ * method call
+ * @throws ProtocolException
+ * if there is an error in the underlying protocol
+ */
+ @Override
+ public final void establishConnection() throws MarshalException, IOException {
+ protocolHandler.writeHandshake(ProtocolType.SINGLE_OP);
+ }
+
+ /**
+ * Writes the call request data into the connection, and reads the
+ * results of the execution in the server.
+ *
+ * @param args
+ * the arguments of the invocation
+ * @param waitReturn
+ * this parameter indicates whether or not to wait for a return
+ * value
+ * @return the return value of the remote method call
+ * @throws Exception
+ * if any exception is thrown on the server side
+ */
+ @Override
+ protected final Object methodCall(ObjID objId, long hash, Object[] args,
+ boolean waitReturn) throws Exception {
+ @SuppressWarnings("unused")
+ UID uid = null;
+ ReturnMessage result = null;
+ TransportManager tm = TransportManager.getTransportManager();
+
+ protocolHandler.writeCall(objId, hash, args);
+ out.flush();
+ protocolHandler.readHandshakeResponse();
+ result = protocolHandler.readResult(waitReturn);
+ uid = result.getUID();
+ if (result.sendsDGCAck()) {
+ tm.acknowledgeDGC(uid, this.ep);
+ }
+ if (result.isException()) {
+ throw result.getException();
+ }
+ return result.getResult();
+ }
+
+ /**
+ * Indicates is this {@link Socket} is reusable.
+ */
+ @Override
+ public boolean isReusable() {
+ return false;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpClientConnection.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpServerConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpServerConnection.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpServerConnection.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpServerConnection.java Tue May 16 06:51:00 2006
@@ -0,0 +1,88 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.rmi.RemoteException;
+
+import ar.org.fitc.rmi.transport.jrmp.Message;
+import ar.org.fitc.rmi.transport.jrmp.MessageType;
+import ar.org.fitc.rmi.transport.jrmp.ProtocolType;
+
+/**
+ * Encapsulates the Server events occurring in the JRMP protocol.
+ *
+ * @author Gustavo Petri
+ */
+final class SingleOpServerConnection extends AbstractServerConnection {
+
+ /**
+ * Creates a new connection to the specified
+ * {@link ar.org.fitc.rmi.transport.EndpointID}
+ *
+ * @param in
+ * the specified {@link InputStream}
+ * @param out
+ * the specified {@link OutputStream}
+ * @param clientEP
+ * the specified {@link ar.org.fitc.rmi.transport.EndpointID}
+ * @param sock
+ * the socket of connection
+ */
+ public SingleOpServerConnection(InputStream in, OutputStream out,
+ EndpointID clientEP, Socket sock) {
+ super(in, out, clientEP, sock);
+ }
+
+ /**
+ * Establishes a connection.
+ *
+ * @throws ProtocolException
+ * if there is an error in the underlying protocol
+ */
+ @Override
+ public final void establishConnection() throws ProtocolException {
+ protocolHandler.readHandShake(ProtocolType.SINGLE_OP);
+ protocolHandler.answerHandshake();
+ }
+
+ /**
+ * Handles the incoming message.
+ *
+ * @throws RemoteException If an exception occurs during message handling.
+ */
+ @Override
+ public final void serve() throws RemoteException {
+ Message msg = protocolHandler.readMessage();
+ MessageType type = msg.getType();
+
+ if (type == MessageType.CALL) {
+ handleCall(msg);
+ } else if (type == MessageType.DGCACK) {
+ handleDGCAck(msg);
+ // Writes the HTTP Response message
+ try {
+ out.flush();
+ } catch (IOException e) {
+ throw new ProtocolException("Exception writing the HTTP DGCAck response");
+ }
+ }
+ }
+
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/SingleOpServerConnection.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamClientConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamClientConnection.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamClientConnection.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamClientConnection.java Tue May 16 06:51:00 2006
@@ -0,0 +1,168 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.rmi.ConnectIOException;
+import java.rmi.MarshalException;
+import java.rmi.server.ObjID;
+import java.rmi.server.UID;
+
+import ar.org.fitc.rmi.transport.jrmp.ProtocolType;
+import ar.org.fitc.rmi.transport.jrmp.ReturnMessage;
+
+/**
+ * Encapsulates the Client events occurring in the JRMP protocol. It creates a
+ * socket for the specified {@link ar.org.fitc.rmi.transport.Endpoint}, it
+ * sends all the parameters in the apropriate order and it waits for the
+ * results.
+ *
+ * @author Gustavo Petri
+ */
+final class StreamClientConnection extends AbstractClientConnection {
+
+ /**
+ * Creates a new connection to the specified
+ * {@link ar.org.fitc.rmi.transport.Endpoint}.
+ *
+ * @param ep
+ * the {@link ar.org.fitc.rmi.transport.Endpoint} to connect
+ * @param sock
+ * the {@link java.net.Socket} to connect
+ * @throws ConnectIOException
+ * if an IOException occurs while making a connection to the
+ * remote host
+ */
+ public StreamClientConnection(Socket sock, Endpoint ep)
+ throws ConnectIOException {
+ super(sock, ep);
+ }
+
+ /**
+ * Establishes a connection.
+ * <li>If {@link #lastUsageTime} is <code>null</code> then starts a
+ * connection.
+ * <li>If the difference between current time and {@link #lastUsageTime} is
+ * bigger or equal than double of the value stored in the table then renew
+ * the connection. The multiplied constant 2 is suggested in this
+ * {@link <a href="http://archives.java.sun.com/cgi-bin/wa?A2=ind0101&L=rmi-users&P=R23746&D=0&I=-3">link</a>}
+ *
+ * @throws MarshalException
+ * if a {@link java.io.IOException} occurs while
+ * marshalling the remote call header, arguments or return value
+ * for a remote method call
+ * @throws IOException
+ * if the socket is closed
+ * @throws ProtocolException
+ * if there is an error in the underlying protocol
+ */
+ @Override
+ public final void establishConnection() throws MarshalException,
+ IOException, ProtocolException {
+
+ if (lastUsageTime == null) {
+ // Initially, by default 1 millisecond.
+ handshake();
+ rttTable.put(this.ep, new Long(1));
+ lastUsageTime = System.currentTimeMillis();
+ } else if (System.currentTimeMillis() - this.lastUsageTime >= (rttTable
+ .get(this.ep) * 2)) {
+ // The multiplied constant 2 is suggested in
+ // http://archives.java.sun.com/cgi-bin/wa?A2=ind0101&L=rmi-users&P=R23746&D=0&I=-3.
+ Long sentTime = System.currentTimeMillis();
+ protocolHandler.writePing(); // renewConnection();
+ out.flush();
+ protocolHandler.readPingAck();
+ rttTable.put(ep, System.currentTimeMillis() - sentTime);
+ }
+ }
+
+ /**
+ * Writes the initial handshake data, indicating that the Stream protocol
+ * will be used, reads the handshake response from the server, and writes
+ * the client's default Endpoint.
+ *
+ * @throws MarshalException
+ * if an exception occurs while writing the handshake
+ * information.
+ */
+ private final void handshake() throws MarshalException {
+ try {
+ protocolHandler.writeHandshake(ProtocolType.STREAM);
+ out.flush();
+ protocolHandler.readHandshakeResponse();
+ EndpointID.read(in);
+ protocolHandler.writeHandshakeResponse();
+ out.flush();
+ } catch (MarshalException e) {
+ throw new MarshalException("I/O Error Marshaling Transport Header",
+ e);
+ } catch (ProtocolException e) {
+ throw new MarshalException("I/O Error Marshaling Transport Header",
+ e);
+ } catch (IOException e) {
+ throw new MarshalException("Exception marshaling JRMP Header", e);
+ }
+ }
+
+ /**
+ * Writes the call request data into the connection, and reads the results
+ * of the execution in the server.
+ *
+ * @param objId
+ * the specified {@link java.rmi.server.ObjID}
+ * @param args
+ * the arguments of the invocation
+ * @param hash
+ * the specified hash for the invoke method
+ * @param waitReturn
+ * this parameter indicates whether or not to wait for a return
+ * value
+ * @return the return value of the remote method call
+ * @throws Exception
+ * if any exception is thrown on the server side
+ */
+
+ @Override
+ protected final Object methodCall(ObjID objId, long hash, Object[] args,
+ boolean waitReturn) throws Exception {
+ UID uid = null;
+ ReturnMessage result = null;
+
+ protocolHandler.writeCall(objId, hash, args);
+ out.flush();
+ result = protocolHandler.readResult(waitReturn);
+ uid = result.getUID();
+ // FIXME : What do we do with the UID?
+ if (result.sendsDGCAck()) {
+ try {
+ acknowledgeDGC(uid);
+ } catch (ProtocolException e) {
+ // FIXME REVIEW: Not sure this exception must be swallowed.
+ }
+ }
+ if (result.isException()) {
+ throw result.getException();
+ }
+ return result.getResult();
+ }
+
+ @Override
+ public boolean isReusable() {
+ return true;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamClientConnection.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamServerConnection.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamServerConnection.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamServerConnection.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamServerConnection.java Tue May 16 06:51:00 2006
@@ -0,0 +1,102 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.rmi.RemoteException;
+
+import ar.org.fitc.rmi.transport.jrmp.Message;
+import ar.org.fitc.rmi.transport.jrmp.MessageType;
+import ar.org.fitc.rmi.transport.jrmp.ProtocolType;
+
+/**
+ * Encapsulates the Server events occurring in the JRMP protocol.
+ *
+ * @author Gustavo Petri
+ */
+final class StreamServerConnection extends AbstractServerConnection {
+
+ /**
+ * Creates a new connection to the specified
+ * {@link ar.org.fitc.rmi.transport.EndpointID}
+ *
+ * @param in
+ * the specified
+ * {@link InputStream}
+ * @param out
+ * the specified
+ * {@link OutputStream}
+ * @param clientEP
+ * the specified {@link ar.org.fitc.rmi.transport.EndpointID}
+ * @param sock
+ * the socket of connection
+ */
+ public StreamServerConnection(InputStream in, OutputStream out,
+ EndpointID clientEP, Socket sock) {
+ super(in, out, clientEP, sock);
+ }
+
+ /**
+ * Establishes a connection.
+ *
+ * @throws ProtocolException
+ * if there is an error in the underlying protocol
+ */
+ @Override
+ public final void establishConnection() throws ProtocolException {
+ /*
+ * REVIEW: Check what to do with the client's default serving endpoint.
+ */
+ protocolHandler.readHandShake(ProtocolType.STREAM);
+ protocolHandler.answerHandshake();
+ try {
+ out.flush();
+ } catch (IOException e) {
+ throw new ProtocolException(
+ "IOException flushing the socket contents", e);
+ }
+ // ignores the returned ServerProtocolHandler
+ protocolHandler.readEndpointNegotiation();
+ }
+
+ /**
+ * Handles the incoming message.
+ *
+ * @throws RemoteException
+ * If an exception occurs during message handling.
+ */
+ @Override
+ public final void serve() throws RemoteException {
+ Message msg = protocolHandler.readMessage();
+ MessageType type = msg.getType();
+
+ if (type == MessageType.CALL) {
+ handleCall(msg);
+ } else if (type == MessageType.DGCACK) {
+ handleDGCAck(msg);
+ } else if (type == MessageType.PING) {
+ protocolHandler.writePingAck();
+ try {
+ out.flush();
+ } catch (IOException e) {
+ throw new ProtocolException("I/O Error Writing the PingAck");
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/StreamServerConnection.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/TransportManager.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/TransportManager.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/TransportManager.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/TransportManager.java Tue May 16 06:51:00 2006
@@ -0,0 +1,306 @@
+/*
+* 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.transport;
+
+import java.io.IOException;
+import java.rmi.server.ExportException;
+import java.rmi.server.ObjID;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UID;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import ar.org.fitc.rmi.utils.Pair;
+import ar.org.fitc.rmi.utils.ReversibleHashSet;
+
+/**
+ * Serves as a Transport Service Provider for the RMI subsystem. It is
+ * implemented as a singleton, and it provides the methods necesary to handle
+ * exportation (and unexportation) of objects, and also invocation of methods of
+ * remote objects.
+ * <p>
+ * This class contains a mapping of ObjIDs to ports, which will be used to
+ * validate the invocation of a method for a certain object in a certain port.
+ *
+ * @author Gustavo Petri
+ *
+ */
+public final class TransportManager {
+
+ /**
+ * This is a Singleton.
+ */
+ private static TransportManager transportManager;
+
+ /**
+ * A {@link ar.org.fitc.rmi.utils.ReversibleHashSet} for storing the port
+ * and the corresponding {@link java.rmi.server.ObjID}.
+ */
+ private ReversibleHashSet<Integer, ObjID> portObjIDMap;
+
+ /**
+ * Serves as a cache for
+ * {@link ar.org.fitc.rmi.transport.MultiThreadedServer} and its
+ * {@link ar.org.fitc.rmi.transport.Endpoint}, indexed by port.
+ */
+ private HashMap<Integer, Pair<MultiThreadedServer, Endpoint>> serverMap;
+
+ /**
+ * Indexes the ClientHost and
+ * {@link ar.org.fitc.rmi.transport.StreamClientConnection} by ThreadID.
+ */
+ private Map<Long, Pair<String, Integer>> clientConnectionMap;
+
+ /**
+ * Mapping from {@link java.rmi.server.ObjID} to the ThreadID of the threads
+ * executing methods for that {@link java.rmi.server.ObjID}.
+ */
+ private Map<ObjID, Set<Long>> executingThreads;
+
+ /**
+ * A pool of connections.
+ */
+ private ConnectionPool connPool;
+
+ private Map<Integer, RMIServerSocketFactory> portsInUse;
+
+ /**
+ * The getter for the Singleton.
+ *
+ * @return the singleton
+ */
+ public final static synchronized TransportManager getTransportManager() {
+ if (transportManager == null) {
+ transportManager = new TransportManager();
+ }
+ return transportManager;
+ }
+
+ /**
+ * The constructor for the TransportManager.
+ */
+ private TransportManager() {
+ this.portObjIDMap = new ReversibleHashSet<Integer, ObjID>();
+ this.serverMap = new HashMap<Integer, Pair<MultiThreadedServer, Endpoint>>();
+ // This Map needs to be synchronized.
+ this.clientConnectionMap = new ConcurrentHashMap<Long, Pair<String, Integer>>();
+ this.portsInUse = new HashMap<Integer, RMIServerSocketFactory>();
+ this.executingThreads = new ConcurrentHashMap<ObjID, Set<Long>>();
+ this.connPool = new ConnectionPool();
+ transportManager = this;
+ }
+
+ /**
+ * Obtains a ClientConnection and sends a DGCack message
+ *
+ * @param uid
+ * the specified {@link UID}
+ * @param ep
+ * The {@link Endpoint} to acknowledge
+ */
+ protected void acknowledgeDGC(UID uid, Endpoint ep) {
+ AbstractClientConnection cc;
+
+ try {
+ cc = connPool.getClientConnection(ep);
+ cc.acknowledgeDGC(uid);
+ } catch (IOException e) {
+ // FIXME REVIEW: What to do when an exception is thrown here. May be
+ // a logger could be useful.
+ }
+
+ }
+
+ /**
+ * Obtains the {@link #clientConnectionMap}
+ *
+ * @return the {@link #clientConnectionMap}
+ */
+ protected Map<Long, Pair<String, Integer>> getClientConnectionMap() {
+ return clientConnectionMap;
+ }
+
+ /**
+ * Obtains the the {@link #executingThreads}
+ *
+ * @return the the {@link #executingThreads}
+ */
+ protected Map<ObjID, Set<Long>> getExecutingThreads() {
+ return executingThreads;
+ }
+
+
+ /**
+ * Creates a
+ * {@link java.net.ServerSocket} and listens in the port argument Port for
+ * new connectios corresponding to the objects with objID ID. When a new
+ * connection is received it constructs a new {@link MultiThreadedServer} to
+ * handle the requests.
+ *
+ * @param objID
+ * the specified {@link java.rmi.server.ObjID}
+ * @param port
+ * the port of the connection
+ * @param ssf
+ * the specified {@link java.rmi.server.RMIServerSocketFactory}
+ * @param csf
+ * the specified {@link java.rmi.server.RMIClientSocketFactory}
+ * @return the {@link ar.org.fitc.rmi.transport.Endpoint} of the connection
+ * @throws ExportException
+ * if the exportation fails
+ */
+ public final Endpoint export(ObjID objID, int port,
+ RMIServerSocketFactory ssf, RMIClientSocketFactory csf)
+ throws ExportException {
+ Endpoint ep;
+
+ if (serverMap.containsKey(port)) {
+ if (portsInUse.get(port) != ssf) {
+ throw new ExportException("Port Already in use");
+ }
+ portObjIDMap.insert(port, objID);
+ return serverMap.get(port).getSecond();
+ } else if (port > 0) {
+ portsInUse.put(port, ssf);
+ } else if (!serverMap.isEmpty() && port == 0) {
+ int newPort = serverMap.keySet().iterator().next();
+ portObjIDMap.insert(newPort, objID);
+ portsInUse.put(newPort, ssf);
+ return serverMap.get(newPort).getSecond();
+ }
+ MultiThreadedServer multiThreadedServer = new MultiThreadedServer(ssf,
+ port);
+ portObjIDMap.insert(multiThreadedServer.getLocalPort(), objID);
+ ep = new Endpoint(multiThreadedServer.getLocalPort(), csf);
+ serverMap
+ .put(multiThreadedServer.getLocalPort(),
+ new Pair<MultiThreadedServer, Endpoint>(
+ multiThreadedServer, ep));
+ multiThreadedServer.start();
+ return ep;
+ }
+
+ /**
+ * Unexports an object.
+ *
+ * @param objID
+ * the specified {@link java.rmi.server.ObjID}
+ * @param force
+ * <code>true</code> if the object must to be unexported
+ * @return <code>true</code> if the object has been exported, <code>false
+ * </code>
+ * if not.
+ */
+ public final boolean unexport(ObjID objID, boolean force) {
+ boolean ret = true;
+ int port;
+
+ if (executingThreads.containsKey(objID) && !force) {
+ ret = false;
+ } else {
+ port = portObjIDMap.getKeyFromValue(objID);
+ if (portObjIDMap.getValues(port).size() > 1) {
+ portsInUse.remove(portObjIDMap.getKeyFromValue(objID));
+ portObjIDMap.removeValue(objID);
+ } else {
+ portObjIDMap.removeValue(objID);
+ try {
+ serverMap.get(port).getFirst().stopServing();
+ serverMap.remove(port);
+ } catch (IOException e) {
+ // FIXME REVIEW: What to do with this exception?
+ // May be some logging would be useful here.
+ }
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Obtains a ClientConnection and forwards the request to it. If the
+ * used connection is reusable, it is returned to the pool, otherwise is
+ * closed.
+ *
+ * @param objID
+ * the specified {@link java.rmi.server.ObjID}
+ * @param ep
+ * the {@link ar.org.fitc.rmi.transport.Endpoint} of the
+ * connection
+ * @param args
+ * the arguments of the invocation
+ * @param methodHash
+ * the specified hash
+ * @param waitReturn
+ * this parameter indicates whether or not to wait for a return
+ * value
+ * @return the return value of the remote method call
+ * @throws Exception
+ * if any exception is thrown on the server side
+ */
+ public final Object invoke(ObjID objID, Endpoint ep, Object[] args,
+ long methodHash, boolean waitReturn) throws Exception {
+ Object obj;
+ AbstractClientConnection cc = connPool.getClientConnection(ep);
+ obj = cc.invoke(objID, methodHash, args, waitReturn);
+ if (cc.isReusable()) {
+ // only applicable if the connection is reusable
+ connPool.releaseClientConnection(ep, (StreamClientConnection) cc);
+ } else {
+ cc.releaseConnection();
+ }
+ return obj;
+ }
+
+ /**
+ * Obtains the <code>ClientHost</code>
+ *
+ * @return the <code>ClientHost</code>
+ * @throws ServerNotActiveException
+ * if there is no Client executing methods
+ */
+ public final String getClientHost() throws ServerNotActiveException {
+ Pair<String, Integer> ret = clientConnectionMap.get(Thread
+ .currentThread().getId());
+
+ if (ret == null) {
+ throw new ServerNotActiveException(
+ "There is no Client executing methods");
+ }
+ return ret.getFirst();
+ }
+
+ /**
+ * Obtains the <code>ClientConnection</code>
+ *
+ * @return the <code>ClientConnection</code>
+ * @throws ServerNotActiveException
+ * if there is no Client executing methods
+ */
+ public final String getClientConnection() throws ServerNotActiveException {
+ Pair<String, Integer> ret = clientConnectionMap.get(Thread
+ .currentThread().getId());
+
+ if (ret == null) {
+ throw new ServerNotActiveException(
+ "There is no Client executing methods");
+ }
+ return "TCP Connection (" + ret.getSecond() + ")";
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/TransportManager.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpClientOutputStream.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpClientOutputStream.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpClientOutputStream.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpClientOutputStream.java Tue May 16 06:51:00 2006
@@ -0,0 +1,46 @@
+/*
+* 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.transport.http;
+
+import java.io.OutputStream;
+
+/**
+ * Concrete class that additionally sets the <code>header</code> required for
+ * the http's request line (POST)
+ *
+ * @author Diego Raúl Mercado
+ */
+final class HttpClientOutputStream extends HttpOutputStream {
+
+ /**
+ * Calls the inherit constructor with the parameters
+ * <code>socketOutput</code> and <code>localHostAddress</code>. <br>
+ * Then, sets <code>header</code> required for the http's request line
+ * (POST)
+ *
+ * @param socketOutput
+ * the socket's output stream
+ * @param serverPath
+ * the path location of the server
+ * @param localHostAddress
+ * the localHostAddress attached in the http's host header
+ */
+ protected HttpClientOutputStream(OutputStream socketOutput,
+ String serverPath, String localHostAddress) {
+ super(socketOutput, localHostAddress);
+ header = "POST " + serverPath + " HTTP/1.0";
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpClientOutputStream.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpHeaders.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpHeaders.java?rev=406944&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpHeaders.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpHeaders.java Tue May 16 06:51:00 2006
@@ -0,0 +1,91 @@
+/*
+* 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.transport.http;
+
+/**
+ * This enum is used for http tunneling
+ *
+ * @author Diego Raúl Mercado
+ */
+public enum HttpHeaders {
+ /**
+ * the Content-Length key
+ */
+ CONTENT_LENGTH_HEADER("Content-Length"),
+ /**
+ * the Content-Type key
+ */
+ CONTENT_TYPE_HEADER("Content-Type"),
+ /**
+ * the Connection key
+ */
+ CONNECTION_HEADER("Connection"),
+ /**
+ * the Cache-Control key
+ */
+ CACHE_CONTROL_HEADER("Cache-Control"),
+ /**
+ * the Pragma key
+ */
+ PRAGMA_HEADER("Pragma"),
+ /**
+ * the Host key
+ */
+ HOST_HEADER("Host"),
+ /**
+ * the User-Agent key
+ */
+ USER_AGENT_HEADER("User-Agent"),
+ /**
+ * the Accept key
+ */
+ ACCEPT_HEADER("Accept");
+
+ /** Indicates de value of this enum */
+ private String value;
+
+ /**
+ * Constructor
+ *
+ * @param value the value of this enum
+ */
+ private HttpHeaders(String value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value of this enum
+ */
+ @Override
+ public final String toString() {
+ return value;
+ }
+
+ /**
+ * Given a String value, returns the current type
+ *
+ * @param value the value at constructor time
+ * @return the current type or null if is not available
+ */
+ public final static HttpHeaders getEnum(String value) {
+ for (HttpHeaders httpConstant : values()) {
+ if (httpConstant.toString().equalsIgnoreCase(value)) {
+ return httpConstant;
+ }
+ }
+ return null;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi2/src/ar/org/fitc/rmi/transport/http/HttpHeaders.java
------------------------------------------------------------------------------
svn:executable = *