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 [8/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/javasrc...
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMILog.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMILog.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMILog.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMILog.java Thu May 18 13:01:22 2006
@@ -0,0 +1,431 @@
+/*
+ * 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.4 $
+ */
+package org.apache.harmony.rmi.common;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LogRecord;
+import java.util.logging.SimpleFormatter;
+import java.util.logging.StreamHandler;
+
+
+/**
+ * Class containing all RMI logging functionality.
+ *
+ * @author Mikhail A. Markov
+ * @version $Revision: 1.1.2.4 $
+ */
+public class RMILog implements RMIProperties {
+
+ /**
+ * RMI logging level corresponding to Level.OFF value.
+ */
+ public static final Level SILENT = Level.OFF;
+
+ /**
+ * RMI logging level corresponding to Level.FINE value.
+ */
+ public static final Level BRIEF = Level.FINE;
+
+ /**
+ * RMI logging level corresponding to Level.FINER value.
+ */
+ public static final Level VERBOSE = Level.FINER;
+
+ // handler for copying rmi logging messages to System.err
+ private static Handler consoleHandler =
+ (Handler) AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ Handler h = new RMIStreamHandler(System.err);
+ h.setLevel(Level.ALL);
+ return h;
+ }
+ });
+
+ // Logger wrapped in this RMI log.
+ private Logger logger;
+
+ // Handler set by setOutputStream() method.
+ private RMIStreamHandler rmiLogHandler;
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging remote calls on server side.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging remote calls on server side
+ */
+ public static RMILog getServerCallsLog() {
+ return getLog("harmony.rmi.server.call",
+ getBoolean(LOGSERVER_PROP) ? VERBOSE : SILENT);
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging remote calls on client side.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging remote calls on client side
+ */
+ public static RMILog getClientCallsLog() {
+ return getLog("harmony.rmi.client.call",
+ getBoolean(LOGCLIENT_PROP) ? VERBOSE : SILENT);
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging remote reference activity on server side.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging remote reference activity on server side
+ */
+ public static RMILog getServerRefLog() {
+ return getLog("harmony.rmi.server.ref", getString(SERVERLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging remote reference activity on client side.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging remote reference activity on client side
+ */
+ public static RMILog getClientRefLog() {
+ return getLog("harmony.rmi.client.ref", getString(CLIENTLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging DGC activity.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging DGC activity
+ */
+ public static RMILog getDGCLog() {
+ return getLog("harmony.rmi.dgc", getString(DGCLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging activity of default RMIClassLoader provider.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging activity of default RMIClassLoader provider
+ */
+ public static RMILog getLoaderLog() {
+ return getLog("harmony.rmi.loader", getString(LOADERLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging transport-layer activity.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging transport-layer activity
+ */
+ public static RMILog getTransportLog() {
+ return getLog("harmony.rmi.transport.misc",
+ getString(TRANSPORTLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging TCP binding/connection activity.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging TCP binding/connection activity
+ */
+ public static RMILog getTcpTransportLog() {
+ return getLog("harmony.rmi.transport.tcp",
+ getString(TRANSPORTTCPLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method.
+ * Returns RMILog for logging HTTP connections activity.
+ * If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging HTTP connections activity
+ */
+ public static RMILog getProxyTransportLog() {
+ return getLog("harmony.rmi.transport.proxy",
+ getString(TRANSPORTPROXYLOGLEVEL_PROP));
+ }
+
+ /**
+ * Helper method. Returns RMILog for logging Activation/ActivationGroup/Rmid
+ * events. If such a log does not exist, creates it.
+ *
+ * @return RMILog for logging remote calls on server side
+ */
+ public static RMILog getActivationLog() {
+ return getLog("harmony.rmi.activation", getString(ACTIVATIONLOGLEVEL_PROP));
+ }
+
+ /**
+ * Creates RMILog. Underlying logger will have the name 'loggerName'. The
+ * level for created RMILog will be equal to 'logLevel' value.
+ *
+ * @param loggerName
+ * the name of the logger to be obtained
+ *
+ * @param logLevel
+ * the level for RMILog: it should be one of RMI logging levels
+ * (SILENT, BRIEF, VERBOSE or one of levels from
+ * java.util.logging.Level class
+ */
+ public static RMILog getLog(String loggerName, String logLevel) {
+ return getLog(loggerName, parseLevelString(logLevel));
+ }
+
+ /**
+ * Creates RMILog. Underlying logger will have the name 'loggerName'. The
+ * level for created RMILog will be equal to 'logLevel' value.
+ *
+ * @param loggerName the name of the logger to be obtained
+ * @param logLevel the level for RMILog
+ */
+ public static RMILog getLog(String loggerName, final Level logLevel) {
+ final Logger logger = Logger.getLogger(loggerName);
+
+ // add handler for publishing records to System.err
+ RMILog log = (RMILog) AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+
+ if (logger.getLevel() == null
+ || !logger.isLoggable(logLevel)) {
+ logger.setLevel(logLevel);
+ }
+
+ // remove System.err stream handler to avoid
+ // duplications
+ logger.removeHandler(consoleHandler);
+
+ // add System.err stream handler again
+ logger.addHandler(consoleHandler);
+ return new RMILog(logger);
+ }
+ });
+ return log;
+ }
+
+ /**
+ * Parses the given string and returns the corresponding Level object.
+ * Possible values for the incoming string are one of RMI logging
+ * levels (SILENT, BRIEF, VERBOSE or one of levels from
+ * java.util.logging.Level class. If the given string is null or it could
+ * not be parsed then Level.OFF value will be returned.
+ *
+ * @param levelStr String to be parsed
+ *
+ * @return parsed Level or Level.OFF if the given string is null or an
+ * error occured while it's parsing
+ */
+ public static Level parseLevelString(String levelStr) {
+ if (levelStr == null) {
+ return Level.OFF;
+ }
+ levelStr = levelStr.trim().toUpperCase();
+
+ if (levelStr.equals("SILENT")) {
+ return SILENT;
+ } else if (levelStr.equals("BRIEF")) {
+ return BRIEF;
+ } else if (levelStr.equals("VERBOSE")) {
+ return VERBOSE;
+ }
+ Level logLevel = Level.OFF;
+
+ try {
+ logLevel = Level.parse(levelStr);
+ } catch (IllegalArgumentException iae) {
+ }
+ return logLevel;
+ }
+
+ /*
+ * Constructs RMILog containing specified Logger.
+ *
+ * @param logger Logger for RMILog
+ */
+ private RMILog(Logger logger) {
+ this.logger = logger;
+ }
+
+ /**
+ * Checks if underlying logger whould log a message with the specified
+ * level.
+ *
+ * @param l Logging level to be checked
+ *
+ * @return true if underlying logger would log a message with
+ * the specified level and false otherwise
+ */
+ public boolean isLoggable(Level l) {
+ return logger.isLoggable(l);
+ }
+
+ /**
+ * Logs specified message prepended by the current Thread's name
+ * with the given level to the underlying logger.
+ *
+ * @param l logging level of the message
+ * @param msg message to be logged
+ */
+ public void log(Level l, String msg) {
+ if (isLoggable(l)) {
+ String[] logSrc = getLogSource();
+ logger.logp(l, logSrc[0], logSrc[1],
+ Thread.currentThread().getName() + ": " + msg);
+ }
+ }
+
+ /**
+ * Logs specified message prepended by the current Thread's name
+ * and Throwable object with the given level to the underlying logger.
+ *
+ * @param l logging level of the message and Throwable
+ * @param msg message to be logged
+ * @param t Throwable to be logged
+ */
+ public void log(Level l, String msg, Throwable t) {
+ if (isLoggable(l)) {
+ String[] logSrc = getLogSource();
+ logger.logp(l, logSrc[0], logSrc[1],
+ Thread.currentThread().getName() + ": " + msg, t);
+ }
+ }
+
+ /**
+ * Adds additional handler to the underlying logger from the given
+ * OutputStream. If this method with non-null parameter was already called
+ * and thus additional handler already exists, this handler will be replaced
+ * by newly created handler.
+ * This method is intended to be used by RemoteServer.setLog() method.
+ *
+ * @param out OutputStream for additional handler. If it's null then
+ * messages will not be logged to any additional handlers.
+ *
+ * @see RemoteServer.setLog(OutputStream)
+ */
+ public synchronized void setOutputStream(OutputStream out) {
+ if (rmiLogHandler != null) {
+ logger.removeHandler(rmiLogHandler);
+ }
+
+ if (out == null) {
+ rmiLogHandler = null;
+ return;
+ }
+
+ if (!logger.isLoggable(VERBOSE)) {
+ logger.setLevel(VERBOSE);
+ }
+
+ rmiLogHandler = new RMIStreamHandler(out);
+ rmiLogHandler.setLevel(VERBOSE);
+ logger.addHandler(rmiLogHandler);
+ }
+
+ /**
+ * Returns PrintStream where RMI logs messages.
+ * This method is intended to be used by RemoteServer.getLog() method
+ *
+ * @return PrintStream where RMI logs messages (possibly null)
+ *
+ * @see RemoteServer.getLog()
+ */
+ public synchronized PrintStream getPrintStream() {
+ return (rmiLogHandler == null) ? null : rmiLogHandler.ps;
+ }
+
+ // Reads boolean value from the given property name.
+ private static boolean getBoolean(String propName) {
+ return ((Boolean) AccessController.doPrivileged(
+ new GetBooleanPropAction(propName))).booleanValue();
+ }
+
+ // Reads string value from the given property name.
+ private static String getString(String propName) {
+ return (String) AccessController.doPrivileged(
+ new GetStringPropAction(propName));
+ }
+
+ /*
+ * Returns string containing from 2 elements: the name of the class
+ * and the name of the method from which log() method was called.
+ * It's needed for logging the name of the method from which log() method
+ * was called.
+ */
+ private String[] getLogSource() {
+ StackTraceElement[] curST = (new Exception()).getStackTrace();
+
+ // this method is called from appropriate log() method, so required
+ // source will be at 3-rd cell
+ return new String[] {
+ curST[2].getClassName(), curST[2].getMethodName() };
+ }
+
+
+ /*
+ * Handler similar to ConsoleHandler but working with arbitrary
+ * OutputStreams.
+ */
+ private static class RMIStreamHandler extends StreamHandler {
+
+ // PrintStream build from OutputStream provided to constructor
+ PrintStream ps;
+
+ /*
+ * Constructs RMIStreamHandler from the given OutputStream.
+ *
+ * @param out underlying OutputStream for this handler
+ */
+ RMIStreamHandler(OutputStream out) {
+ super(out, new SimpleFormatter());
+ ps = new PrintStream(out);
+ }
+
+ /**
+ * Publish specified LogRecord.
+ *
+ * @param rec LogRecord to be published
+ */
+ public void publish(LogRecord rec) {
+ super.publish(rec);
+ flush();
+ }
+
+ /**
+ * Flushes the underlying OutputStream.
+ */
+ public void close() {
+ flush();
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMILog.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIProperties.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIProperties.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIProperties.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIProperties.java Thu May 18 13:01:22 2006
@@ -0,0 +1,156 @@
+/*
+ * 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.7 $
+ */
+package org.apache.harmony.rmi.common;
+
+
+/**
+ * Interface containing names of all supported RMI properties.
+ *
+ * @author Mikhail A. Markov, Vasily Zakharov
+ * @version $Revision: 1.1.2.7 $
+ */
+public interface RMIProperties {
+
+ /*
+ * -------------------------------------------------------------------------
+ * java.rmi.* supported properties
+ * -------------------------------------------------------------------------
+ */
+ String ACTIVATIONPORT_PROP = "java.rmi.activation.port";
+ String DGCLEASEVALUE_PROP = "java.rmi.dgc.leaseValue";
+ String CODEBASE_PROP = "java.rmi.server.codebase";
+ String HOSTNAME_PROP = "java.rmi.server.hostname";
+ String LOGSERVER_PROP = "java.rmi.server.logCalls";
+ String RANDOMIDS_PROP = "java.rmi.server.randomIDs";
+ String USECODEBASEONLY_PROP = "java.rmi.server.usecodebaseOnly";
+ String USELOCALHOSTNAME_PROP = "java.rmi.server.useLocalHostname";
+ String DISABLEHTTP_PROP = "java.rmi.server.disableHttp";
+ String IGNORESTUBCLASSES_PROP = "java.rmi.server.ignoreStubClasses";
+
+ /*
+ * -------------------------------------------------------------------------
+ * harmony.rmi.* supported properties
+ * -------------------------------------------------------------------------
+ */
+
+ // Server properties.
+ String DGCACKTIMEOUT_PROP = "harmony.rmi.dgc.ackTimeout";
+ String DGCCHECKINTERVAL_PROP = "harmony.rmi.dgc.checkInterval";
+ String DGCLOGLEVEL_PROP = "harmony.rmi.dgc.logLevel";
+ String LOADERLOGLEVEL_PROP = "harmony.rmi.loader.logLevel";
+ String EXCEPTIONTRACE_PROP = "harmony.rmi.server.exceptionTrace";
+ String SUPPRESSSTACKTRACES_PROP = "harmony.rmi.server.suppressStackTraces";
+ String TRANSPORTLOGLEVEL_PROP = "harmony.rmi.transport.logLevel";
+ String LOCALHOSTNAMETIMEOUT_PROP = "harmony.rmi.transport.tcp.localHostNameTimeOut";
+ String TRANSPORTTCPLOGLEVEL_PROP = "harmony.rmi.transport.tcp.logLevel";
+ String READTIMEOUT_PROP = "harmony.rmi.transport.tcp.readTimeout";
+
+ // Client properties.
+ String LOGCLIENT_PROP = "harmony.rmi.client.logCalls";
+ String DGCCLEANINTERVAL_PROP = "harmony.rmi.dgc.cleanInterval";
+ String SERVERLOGLEVEL_PROP = "harmony.rmi.server.logLevel";
+ String CLIENTLOGLEVEL_PROP = "harmony.rmi.client.logLevel";
+ String CONNECTIONTIMEOUT_PROP = "harmony.rmi.transport.connectionTimeout";
+ String CONNECTTIMEOUT_PROP = "harmony.rmi.transport.proxy.connectTimeout";
+ String EAGERHTTPFALLBACK_PROP = "harmony.rmi.transport.proxy.eagerHttpFallback";
+ String TRANSPORTPROXYLOGLEVEL_PROP = "harmony.rmi.transport.proxy.logLevel";
+ String HANDSHAKETIMEOUT_PROP = "harmony.rmi.transport.tcp.handshakeTimeout";
+
+ // Activation properties.
+ String ACTIVATIONLOGLEVEL_PROP = "harmony.rmi.activation.logLevel";
+ String ACTIVATION_EXECTIMEOUT_PROP = "harmony.rmi.activation.execTimeout";
+ String MAXSTARTGROUP_PROP = "harmony.rmi.activation.groupThrottle";
+ String ACTIVATION_SNAPSHOTINTERVAL_PROP = "harmony.rmi.activation.snapshotInterval";
+ String ACTIVATION_LOG_DEBUG_PROP = "harmony.rmi.log.debug";
+ String ACTIVATION_DEBUGEXEC_PROP = "harmony.rmi.server.activation.debugExec";
+
+ /*
+ * -------------------------------------------------------------------------
+ * Additional proxy properties
+ * -------------------------------------------------------------------------
+ */
+
+ /**
+ * Name of the system property containing HTTP proxy host name.
+ */
+ String PROXY_HOST_PROP = "http.proxyHost";
+
+ /**
+ * Name of the system property containing HTTP proxy port number.
+ */
+ String PROXY_PORT_PROP = "http.proxyPort";
+
+ /**
+ * Name of the property allowing to disable direct socket connections.
+ */
+ String DISABLE_DIRECT_SOCKET_PROP =
+ "org.apache.harmony.rmi.transport.disableDirectSocket";
+
+ /**
+ * Name of the property allowing to enable direct HTTP connections.
+ */
+ String ENABLE_DIRECT_HTTP_PROP =
+ "org.apache.harmony.rmi.transport.proxy.enableDirectHTTP";
+
+ /**
+ * Name of the property allowing to disable plain HTTP connections
+ * (and force CGI instead).
+ */
+ String DISABLE_PLAIN_HTTP_PROP =
+ "org.apache.harmony.rmi.transport.proxy.disablePlainHTTP";
+
+ /*
+ * -------------------------------------------------------------------------
+ * Additional Activation properties
+ * -------------------------------------------------------------------------
+ */
+
+ /**
+ * @see org.apache.harmony.rmi.common.RMIConstants#DEFAULT_ACTIVATION_MONITOR_CLASS_NAME
+ */
+ String ACTIVATION_MONITOR_CLASS_NAME_PROP =
+ "org.apache.harmony.rmi.activation.monitor";
+
+ /*
+ * -------------------------------------------------------------------------
+ * RMI Compiler properties
+ * -------------------------------------------------------------------------
+ */
+
+ /**
+ * Property specifying the compiler class to use.
+ */
+ String JAVA_COMPILER_CLASS_PROPERTY =
+ "org.apache.harmony.rmi.compiler.class";
+
+ /**
+ * Property specifying the compiler class method to use.
+ */
+ String JAVA_COMPILER_METHOD_PROPERTY =
+ "org.apache.harmony.rmi.compiler.method";
+
+ /**
+ * Property specifying the compiler executable to use.
+ */
+ String JAVA_COMPILER_EXECUTABLE_PROPERTY =
+ "org.apache.harmony.rmi.compiler.executable";
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIProperties.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIUtil.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIUtil.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIUtil.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIUtil.java Thu May 18 13:01:22 2006
@@ -0,0 +1,626 @@
+/*
+ * 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.3 $
+ */
+package org.apache.harmony.rmi.common;
+
+import java.io.IOException;
+
+import java.lang.reflect.Method;
+
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Utility class for RMI implementation.
+ *
+ * This class cannot be instantiated.
+ *
+ * @author Mikhail A. Markov, Vasily Zakharov
+ * @version $Revision: 1.1.2.3 $
+ */
+public final class RMIUtil {
+
+ /**
+ * This class cannot be instantiated.
+ */
+ private RMIUtil() {}
+
+ /**
+ * Returns wrapping Object class for specified primitive class.
+ *
+ * @param cls
+ * Class to wrap.
+ *
+ * @return Wrapping Object class for <code>cls</code>, if <code>cls</code>
+ * is Object class itself (e. g. <code>Vector</code>),
+ * <code>cls</code> itself is returned, for primitive types
+ * (e. g. <code>int</code>) the respective wrapping Object class
+ * is returned (in case of <code>int</code>, {@link Integer}).
+ */
+ public static Class getWrappingClass(Class cls) {
+ if (cls == boolean.class) {
+ return Boolean.class;
+ } else if (cls == char.class) {
+ return Character.class;
+ } else if (cls == byte.class) {
+ return Byte.class;
+ } else if (cls == short.class) {
+ return Short.class;
+ } else if (cls == int.class) {
+ return Integer.class;
+ } else if (cls == long.class) {
+ return Long.class;
+ } else if (cls == float.class) {
+ return Float.class;
+ } else if (cls == double.class) {
+ return Double.class;
+ } else if (cls == void.class) {
+ return Void.class;
+ } else { // Object type.
+ return cls;
+ }
+ }
+
+ /**
+ * Returns package name for the class.
+ *
+ * @param cls
+ * Class to get package name for.
+ *
+ * @return Package name of the class,
+ * or <code>null</code> if class does not belong to a package.
+ */
+ public static String getPackageName(Class cls) {
+ if (cls.isArray() || cls.isPrimitive()) {
+ return null;
+ }
+ String name = cls.getName();
+ int index = name.lastIndexOf('.');
+
+ return ((index > 0) ? name.substring(0, index) : null);
+ }
+
+ /**
+ * Returns canonical name for the class, e. g. full class name with
+ * package name, with <code>[]</code> appended to the end for array types.
+ * Handles local classes correctly.
+ *
+ * @param cls
+ * Class to get canonical name for.
+ *
+ * @return Canonical name of the class.
+ *
+ * @todo Remove completely for Java 5.0 in favor of
+ * <code>Class.getCanonicalName()</code>.
+ */
+ public static String getCanonicalName(Class cls) {
+ if (cls.isArray()) {
+ // Use recursion to create name for array class.
+ return (getCanonicalName(cls.getComponentType()) + "[]");
+ }
+ Class declaring = cls.getDeclaringClass();
+
+ if (declaring != null) {
+ // Use recursion to create name for local classes.
+ return (getCanonicalName(declaring) + '.' + getSimpleName(cls));
+ }
+ return cls.getName();
+ }
+
+ /**
+ * Returns short canonical name for the class, e. g. short class name
+ * without package name (but with '.' symbols for local classes),
+ * with <code>[]</code> appended to the end for array types.
+ *
+ * @param cls
+ * Class to get short canonical name for.
+ *
+ * @return Short canonical name of the class.
+ */
+ public static String getShortCanonicalName(Class cls) {
+ if (cls.isArray()) {
+ // Use recursion to create name for array class.
+ return (getShortCanonicalName(cls.getComponentType()) + "[]");
+ }
+
+ // The last dot in full name separates class name from package name.
+ int index = cls.getName().lastIndexOf('.');
+
+ // Canonical name uses dots to separate local class names.
+ String name = getCanonicalName(cls);
+
+ return ((index > 0) ? name.substring(index + 1) : name);
+ }
+
+ /**
+ * Returns short name for the class, e. g. short class name without
+ * package name (but with '$' symbols for local classes),
+ * with <code>[]</code> appended to the end for array types.
+ *
+ * @param cls
+ * Class to get short name for.
+ *
+ * @return Short name of the class.
+ */
+ public static String getShortName(Class cls) {
+ if (cls.isArray()) {
+ // Use recursion to create name for array class.
+ return (getShortName(cls.getComponentType()) + "[]");
+ }
+ String name = cls.getName();
+ int index = name.lastIndexOf('.');
+
+ return ((index > 0) ? name.substring(index + 1) : name);
+ }
+
+ /**
+ * Returns simple name for the class, e. g. short class name without
+ * package name or declaring class name, with <code>[]</code> appended
+ * to the end for array types.
+ *
+ * @param cls
+ * Class to get simple name for.
+ *
+ * @return Simple name of the class.
+ *
+ * @todo Remove completely for Java 5.0 in favor of
+ * <code>Class.getSimpleName()</code>.
+ */
+ public static String getSimpleName(Class cls) {
+ if (cls.isArray()) {
+ // Use recursion to create name for array class.
+ return (getSimpleName(cls.getComponentType()) + "[]");
+ }
+ String name = cls.getName();
+ Class declaring = cls.getDeclaringClass();
+
+ if (declaring != null) {
+ // Use substringing to extract simple name of a local class.
+ return (name.substring(declaring.getName().length() + 1));
+ }
+ int index = name.lastIndexOf('.');
+
+ return ((index > 0) ? name.substring(index + 1) : name);
+ }
+
+ /**
+ * Returns system name for the class, e. g.
+ * <code>I</code> for <code>int</code>,
+ * <code>[[B</code> for <code>boolean[][]</code>,
+ * <code>[Ljava/lang/String;</code> for <code>String[]</code>.
+ *
+ * @param cls
+ * Class to get system name for.
+ *
+ * @return System name of the class.
+ */
+ public static String getSystemName(Class cls) {
+ if (cls == boolean.class) {
+ return "Z";
+ } else if (cls == char.class) {
+ return "C";
+ } else if (cls == byte.class) {
+ return "B";
+ } else if (cls == short.class) {
+ return "S";
+ } else if (cls == int.class) {
+ return "I";
+ } else if (cls == long.class) {
+ return "J";
+ } else if (cls == float.class) {
+ return "F";
+ } else if (cls == double.class) {
+ return "D";
+ } else if (cls == void.class) {
+ return "V";
+ } else { // Object type.
+ String className = cls.getName().replace('.', '/');
+
+ // Add reference to non-array reference types.
+ return (cls.isArray() ? className : ('L' + className + ';'));
+ }
+ }
+
+ /**
+ * Returns method descriptor as specified in section 4.3.3
+ * of Virtual Machine Specification.
+ *
+ * @param method
+ * Method to return descriptor for.
+ *
+ * @return Method descriptor.
+ */
+ public static String getMethodDescriptor(Method method) {
+ StringBuffer buffer = new StringBuffer().append('(');
+ Class[] parameters = method.getParameterTypes();
+
+ for (int i = 0; i < parameters.length; i++) {
+ buffer.append(getSystemName(parameters[i]));
+ }
+ buffer.append(')').append(getSystemName(method.getReturnType()));
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns extended method descriptor,
+ * i. e. method name appended with method descriptor
+ * as specified in section 4.3.3
+ * of Virtual Machine Specification.
+ *
+ * @param method
+ * Method to return extended descriptor for.
+ *
+ * @return Extended method descriptor.
+ */
+ public static String getExtendedMethodDescriptor(Method method) {
+ return (method.getName() + getMethodDescriptor(method));
+ }
+
+ /**
+ * Returns basic method signature (method name and full parameters
+ * class names) for the method.
+ *
+ * @param method
+ * Method to get basic signature for.
+ *
+ * @return Basic method signature (method name and full parameters
+ * class names) for the method. For example, for this particular
+ * method the long signature will be: <code>
+ * "getBasicMethodSignature(java.lang.reflect.Method)"</code>.
+ */
+ public static String getBasicMethodSignature(Method method) {
+ // Start with method name.
+ StringBuffer buffer = new StringBuffer()
+ .append(method.getName()).append('(');
+ Class[] parameters = method.getParameterTypes();
+
+ // Append names of parameter types.
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ buffer.append(getCanonicalName(parameters[i]));
+ }
+ return buffer.append(')').toString();
+ }
+
+ /**
+ * Returns long method signature (return type, method name and full
+ * parameters class names) for the method.
+ *
+ * @param method
+ * Method to get long signature for.
+ *
+ * @return Long method signature (return type, method name and full
+ * parameters class names) for the method. For example, for this
+ * particular method the long signature will be: <code>
+ * "java.lang.String
+ * getLongMethodSignature(java.lang.reflect.Method)"</code>.
+ */
+ public static String getLongMethodSignature(Method method) {
+ StringBuffer suffix = new StringBuffer();
+ Class cls = method.getReturnType();
+
+ // Create signature suffix for array types.
+ while (cls.isArray()) {
+ suffix.append("[]");
+ cls = cls.getComponentType();
+ }
+ return (getCanonicalName(cls) + ' '
+ + getBasicMethodSignature(method) + suffix);
+ }
+
+ /**
+ * Returns short method signature (without return type,
+ * declaring class name or parameters package names) for the method.
+ *
+ * @param method
+ * Method to get short signature for.
+ *
+ * @return Short method signature (without return type,
+ * declaring class name or parameters package names)
+ * for the method. For example, for this particular method
+ * the short signature will be:
+ * <code>"getShortMethodSignature(Method)"</code>.
+ */
+ public static String getShortMethodSignature(Method method) {
+ // Start with method name.
+ StringBuffer buffer = new StringBuffer(method.getName() + '(');
+ Class[] parameters = method.getParameterTypes();
+
+ // Append short names of parameter types.
+ for (int i = 0; i < parameters.length; i++) {
+ buffer.append(((i > 0) ? ", " : "")
+ + getShortCanonicalName(parameters[i]));
+ }
+ return buffer.append(')').toString();
+ }
+
+ /**
+ * Validates remote interface.
+ * Particularly, checks that all methods throw {@link RemoteException}.
+ *
+ * @param iface
+ * Interface to validate.
+ *
+ * @return <code>true</code> if the specified class is a valid remote
+ * interface, <code>false</code> if the specified class is not
+ * a remote interface.
+ *
+ * @throws IllegalArgumentException
+ * If specified class is not an interface or if it implements
+ * {@link java.rmi.Remote} but is not a valid remote interface.
+ */
+ public static boolean checkRemoteInterface(Class iface)
+ throws IllegalArgumentException {
+ if (!iface.isInterface()) {
+ // This is not an interface.
+ throw new IllegalArgumentException(iface.getName()
+ + " is not an interface");
+ }
+
+ if (!Remote.class.isAssignableFrom(iface)) {
+ // This is not a remote interface.
+ return false;
+ }
+
+ // Extract all methods from the specified interface.
+ Method methods[] = iface.getMethods();
+
+ methods:
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+
+ // Extract thrown exceptions list from a particular method.
+ Iterator j = Arrays.asList(method.getExceptionTypes()).iterator();
+
+ while (j.hasNext()) {
+ // Search for exception that extends RemoteException.
+ if (((Class) j.next()).isAssignableFrom(RemoteException.class))
+ continue methods;
+ }
+ throw new IllegalArgumentException(iface.getName()
+ + " is not a valid remote interface: method "
+ + getBasicMethodSignature(method)
+ + " must throw java.rmi.RemoteException");
+ }
+ return true;
+ }
+
+ /**
+ * Returns the list of implemented remote interfaces for the specified
+ * class.
+ *
+ * @param cls
+ * Class to return list of remote interfaces for.
+ *
+ * @return Array of remote interfaces implemented by the specified class.
+ * May be empty if the specified class is not a remote class
+ * or if <code>cls</code> is <code>null</code>.
+ *
+ * @throws IllegalArgumentException
+ * If class implements any invalid remote interfaces.
+ */
+ public static Class[] getRemoteInterfaces(Class cls)
+ throws IllegalArgumentException {
+ List interfaces = new LinkedList();
+
+ for (; cls != null; cls = cls.getSuperclass()) {
+ // Get the list of interfaces the class implements.
+ Class[] interfacesArray = cls.getInterfaces();
+
+ // Walk through all interfaces the class implements.
+ for (int i = 0; i < interfacesArray.length; i++) {
+ Class iface = interfacesArray[i];
+
+ // Ignore duplicates and non-Remote interfaces.
+ if (!interfaces.contains(iface)
+ && checkRemoteInterface(iface)) {
+ // Add this interface to the interfaces table.
+ interfaces.add(iface);
+ }
+ }
+ }
+ return (Class[]) interfaces.toArray(new Class[interfaces.size()]);
+ }
+
+ /**
+ * Returns the string representation of the list of remote interfaces
+ * implemented by the specified class.
+ *
+ * @param cls
+ * Class to find remote interfaces for.
+ *
+ * @return List of remote interfaces for the specified class.
+ *
+ * @throws IllegalArgumentException
+ * If some error occured while creating the list.
+ */
+ public static String[] getRemoteInterfacesNames(Class cls)
+ throws IllegalArgumentException {
+ Class[] interfaces = getRemoteInterfaces(cls);
+
+ if ((interfaces == null) || (interfaces.length == 0)) {
+ return new String[0];
+ }
+ String[] interfStr = new String[interfaces.length];
+
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfStr[i] = interfaces[i].getName();
+ }
+ return interfStr;
+ }
+
+ /**
+ * Returns a map containing all remote methods of the specified class
+ * (i. e. all methods contained in {@link Remote} interfaces implemented
+ * by the class). Hashes of methods are keys in this map.
+ *
+ * @param cls
+ * Class to list remote methods for.
+ *
+ * @return Map containing all the remote methods of the specified class
+ * and having method hashes as keys.
+ *
+ * @throws RMIHashException
+ * If error occured while calculating method hash.
+ */
+ public static Map getRemoteMethods(Class cls) throws RMIHashException {
+ Map map = new HashMap();
+
+ for (; cls != null; cls = cls.getSuperclass()) {
+ Class[] interf = cls.getInterfaces();
+
+ for (int i = 0; i < interf.length; ++i) {
+ if (!Remote.class.isAssignableFrom(interf[i])) {
+ continue;
+ }
+ Method[] m = interf[i].getMethods();
+
+ for (int j = 0; j < m.length; ++j) {
+ // Calculate the hash for the method.
+ long hash = RMIHash.getMethodHash(m[j]);
+ map.put(new Long(hash), m[j]);
+ }
+ }
+ }
+ return map;
+ }
+
+ /**
+ * Finds the superclass of the specified class that directly implements
+ * remote interface(s).
+ *
+ * @param cls
+ * Class to check for remote superclass.
+ *
+ * @return The class found.
+ *
+ * @throws IllegalArgumentException
+ * If the specified class is not remote.
+ */
+ public static Class getRemoteClass(Class cls)
+ throws IllegalArgumentException {
+ for (; cls != null; cls = cls.getSuperclass()) {
+ Class[] interfaces = cls.getInterfaces();
+
+ for (int i = 0; i < interfaces.length; ++i) {
+ if (Remote.class.isAssignableFrom(interfaces[i])) {
+ return cls;
+ }
+ }
+ }
+ throw new IllegalArgumentException("The specified class is not remote");
+ }
+
+ /**
+ * Returns <code>true</code> if the specified hostName is a local host
+ * and <code>false</code> otherwise.
+ *
+ * @param hostName
+ * The name of the host to check.
+ *
+ * @return <code>true</code> if the specified hostName is a local host
+ * and <code>false</code> otherwise.
+ *
+ * @throws UnknownHostException
+ * If the specified host name could not be resolved.
+ */
+ public static boolean isLocalHost(final String hostName)
+ throws UnknownHostException {
+ if (hostName == null) {
+ return true;
+ }
+
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws UnknownHostException, IOException {
+ // Resolve the host name.
+ InetAddress hostAddr = InetAddress.getByName(hostName);
+
+ // Check if this address is really local.
+ ServerSocket ss = new ServerSocket(0, 1, hostAddr);
+
+ try {
+ ss.close();
+ } catch (IOException ioe) {
+ // Ignoring.
+ }
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ Exception ex = pae.getException();
+
+ if (ex instanceof UnknownHostException) {
+ throw (UnknownHostException) ex;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns <code>true</code> if the first specified class loader
+ * is a parent class loader (or equal) to the second specified class loader
+ * and <code>false</code> otherwise.
+ *
+ * @param cl1
+ * First class loader.
+ *
+ * @param cl2
+ * Second class loader.
+ *
+ * @return <code>true</code> if the first class loader is a parent
+ * (or equal) to the second class loader.
+ */
+ public static boolean isParentLoader(ClassLoader cl1, ClassLoader cl2) {
+ if (cl1 == null) {
+ // cl1 is a bootstrap or system class loader.
+ return true;
+ }
+
+ for (; cl2 != null; cl2 = cl2.getParent()) {
+ if (cl1 == cl2) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/RMIUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/SubProcess.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/SubProcess.java?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/SubProcess.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/SubProcess.java Thu May 18 13:01:22 2006
@@ -0,0 +1,830 @@
+/*
+ * 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.2 $
+ */
+package org.apache.harmony.rmi.common;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/**
+ * Allows for execution of external applications as subprocesses.
+ *
+ * @author Vasily Zakharov
+ * @version $Revision: 1.1.2.2 $
+ *
+ * @todo Check with <code>ProcessBuilder</code> for Java 5.0.
+ */
+public final class SubProcess {
+
+ /**
+ * Default argument to {@link #tell(String)}
+ * and expect {@link #expect(String)} methods.
+ */
+ public static final String READY_STRING = "PROCESS_READY";
+
+ /**
+ * Process.
+ */
+ private Process process;
+
+ /**
+ * Data input stream.
+ */
+ private DataInputStream dataInput;
+
+ /**
+ * Data output stream.
+ */
+ private DataOutputStream dataOutput;
+
+ /**
+ * Data error stream.
+ */
+ private DataInputStream dataError;
+
+ /**
+ * Process input stream.
+ */
+ private InputStream processInput;
+
+ /**
+ * Process output stream.
+ */
+ private OutputStream processOutput;
+
+ /**
+ * Process error stream.
+ */
+ private InputStream processError;
+
+ /**
+ * Pipe target input stream.
+ */
+ private InputStream targetInput;
+
+ /**
+ * Pipe target output stream.
+ */
+ private OutputStream targetOutput;
+
+ /**
+ * Pipe target error stream.
+ */
+ private OutputStream targetError;
+
+ /**
+ * Creates subprocess with full control of its streams.
+
+ * Equivalent to
+ * {@link #SubProcess(String[], boolean, OutputStream, boolean, InputStream, boolean, OutputStream)
+ * SubProcess(args, true, System.out, true, System.in, true, System.err)}.
+ *
+ * @param args
+ * Program name and command line arguments
+ * (as for {@link Runtime#exec(String[])}).
+ *
+ * @throws IOException
+ */
+ public SubProcess(String[] args) throws IOException {
+ this(args, true, System.out, true, System.in, true, System.err);
+ }
+
+ /**
+ * Creates instance of this class with no control of its streams.
+ * If <code>pipe</code> is <code>true</code>, the streams are piped
+ * to the respective system streams of the current process.
+ * This is equivalent to
+ * {@link #SubProcess(String[], boolean, OutputStream, boolean, InputStream, boolean, OutputStream)
+ * SubProcess(args, false, System.out, false, System.in, false, System.err)}.
+ *
+ * If <code>pipe</code> is <code>false</code>, the streams are discarded.
+ * This is equivalent to
+ * {@link #SubProcess(String[], boolean, OutputStream, boolean, InputStream, boolean, OutputStream)
+ * SubProcess(args, false, null, false, null, false, null)}.
+ *
+ * @param args
+ * Program name and command line arguments
+ * (as for {@link Runtime#exec(String[])}).
+ *
+ * @param pipe
+ * If <code>true</code>, the streams are piped
+ * to the respective system streams of the current process,
+ * if <code>false</code>, the streams are discarded.
+ *
+ * @throws IOException
+ */
+ public SubProcess(String[] args, boolean pipe) throws IOException {
+ this(args, false, (pipe ? System.out : null),
+ false, (pipe ? System.in : null),
+ false, (pipe ? System.err : null));
+ }
+
+ /**
+ * Creates instance of this class with no control of its streams.
+ * This is equivalent to
+ * {@link #SubProcess(String[], boolean, OutputStream, boolean, InputStream, boolean, OutputStream)
+ * SubProcess(args, false, outputStream, false, inputStream, false, errorStream)}.
+ *
+ * @param args
+ * Program name and command line arguments
+ * (as for {@link Runtime#exec(String[])}).
+ *
+ * @param outputStream
+ * Output stream to pipe program input to
+ * if <code>inputControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case input from the program is discarded.
+ *
+ * @param inputStream
+ * Input stream to pipe to the program output stream
+ * if <code>outputControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case the program output stream is closed.
+ *
+ * @param errorStream
+ * Error stream to pipe program error input to
+ * if <code>errorControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case error input from the program is discarded.
+ *
+ * @throws IOException
+ */
+ public SubProcess(String[] args,
+ OutputStream outputStream, InputStream inputStream,
+ OutputStream errorStream) throws IOException {
+ this(args, false, outputStream, false, inputStream, false, errorStream);
+ }
+
+ /**
+ * Creates instance of this class.
+ *
+ * @param args
+ * Program name and command line arguments
+ * (as for {@link Runtime#exec(String[])}).
+ *
+ * @param inputControl
+ * If <code>true</code>, input from the program is available
+ * to {@link #expect()} methods and <code>outputStream</code>
+ * parameter is ignored, otherwise it is piped to the specified
+ * <code>outputStream</code>.
+ *
+ * @param outputStream
+ * Output stream to pipe program input to
+ * if <code>inputControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case input from the program is discarded.
+ *
+ * @param outputControl
+ * If <code>true</code>, output stream to the program is available
+ * to {@link #tell()} methods and <code>inputStream</code>
+ * parameter is ignored, otherwise the specified
+ * <code>inputStream</code> is piped to program output stream.
+ *
+ * @param inputStream
+ * Input stream to pipe to the program output stream
+ * if <code>outputControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case the program output stream is closed.
+ *
+ * @param errorControl
+ * If <code>true</code>, error input from the program is available
+ * to {@link #expectError()} methods and <code>errorStream</code>
+ * parameter is ignored, otherwise it is piped to the specified
+ * <code>errorStream</code>.
+ *
+ * @param errorStream
+ * Error stream to pipe program error input to
+ * if <code>errorControl</code> is <code>false</code>.
+ * May be <code>null</code>,
+ * in this case error input from the program is discarded.
+ *
+ * @throws IOException
+ */
+ public SubProcess(String[] args,
+ boolean inputControl, OutputStream outputStream,
+ boolean outputControl, InputStream inputStream,
+ boolean errorControl, OutputStream errorStream) throws IOException {
+ process = Runtime.getRuntime().exec(args);
+
+ processInput = process.getInputStream();
+ processOutput = process.getOutputStream();
+ processError = process.getErrorStream();
+
+ targetInput = inputStream;
+ targetOutput = outputStream;
+ targetError = errorStream;
+
+ if (inputControl) {
+ dataInput = new DataInputStream(processInput);
+ } else {
+ dataInput = null;
+ doPipeInput();
+ }
+
+ if (outputControl) {
+ dataOutput = new DataOutputStream(processOutput);
+ } else {
+ dataOutput = null;
+ doPipeOutput();
+ }
+
+ if (errorControl) {
+ dataError = new DataInputStream(processError);
+ } else {
+ dataError = null;
+ doPipeError();
+ }
+ }
+
+ /**
+ * Discards the remaining input.
+ * Usable when <code>inputControl</code> is enabled
+ * but there's nothing else to {@linkplain #expect() expect}.
+ */
+ public void discardInput() {
+ pipeInput(null);
+ }
+
+ /**
+ * Pipes the remaining input to the target output stream
+ * specified in <a href="#constructor_detail">constructor</a>.
+ * Usable when <code>inputControl</code> is enabled
+ * but there's nothing else to {@linkplain #expect() expect}.
+ */
+ public void pipeInput() {
+ pipeInput(targetOutput);
+ }
+
+ /**
+ * Pipes the remaining input to the specified output stream.
+ * Usable when <code>inputControl</code> is enabled
+ * but there's nothing else to {@linkplain #expect() expect}.
+ *
+ * @param outputStream
+ * Output stream to pipe program input to.
+ * May be <code>null</code>,
+ * in this case input from the program is discarded.
+ */
+ public void pipeInput(OutputStream outputStream) {
+ if (dataInput != null) {
+ dataInput = null;
+ targetOutput = outputStream;
+ doPipeInput();
+ }
+ }
+
+ /**
+ * Creates pipe from process input to target output.
+ */
+ private void doPipeInput() {
+ new StreamPipe(processInput, targetOutput).start();
+ }
+
+ /**
+ * Closes the program output.
+ * Usable when <code>outputControl</code> is enabled
+ * but there's nothing else to {@linkplain #tell() tell}.
+ */
+ public void closeOutput() {
+ pipeOutput(null);
+ }
+
+ /**
+ * Pipes the target input stream specified in
+ * <a href="#constructor_detail">constructor</a>
+ * to the program output stream.
+ * Usable when <code>outputControl</code> is enabled
+ * but there's nothing else to {@linkplain #tell() tell}.
+ */
+ public void pipeOutput() {
+ pipeOutput(targetInput);
+ }
+
+ /**
+ * Pipes the specified input stream to the program output stream.
+ * Usable when <code>outputControl</code> is enabled
+ * but there's nothing else to {@linkplain #tell() tell}.
+ *
+ * @param inputStream
+ * Input stream to pipe to the program output.
+ * May be <code>null</code>,
+ * in this case the program output stream is closed.
+ */
+ public void pipeOutput(InputStream inputStream) {
+ if (dataOutput != null) {
+ dataOutput = null;
+ targetInput = inputStream;
+ doPipeOutput();
+ }
+ }
+
+ /**
+ * Creates pipe from target input to process output
+ * or closes process output if target input is <code>null</code>.
+ */
+ private void doPipeOutput() {
+ if (targetInput != null) {
+ new StreamPipe(targetInput, processOutput).start();
+ } else {
+ try {
+ processOutput.close();
+ } catch (IOException e) {}
+ }
+ }
+
+ /**
+ * Discards the remaining error input.
+ * Usable when <code>errorControl</code> is enabled
+ * but there's nothing else to {@linkplain #expectError() expect}.
+ */
+ public void discardError() {
+ pipeError(null);
+ }
+
+ /**
+ * Pipes the remaining error input to the target error stream
+ * specified in <a href="#constructor_detail">constructor</a>.
+ * Usable when <code>errorControl</code> is enabled
+ * but there's nothing else to {@linkplain #expectError() expect}.
+ */
+ public void pipeError() {
+ pipeError(targetError);
+ }
+
+ /**
+ * Pipes the remaining error input to the specified error stream.
+ * Usable when <code>errorControl</code> is enabled
+ * but there's nothing else to {@linkplain #expectError() expect}.
+ *
+ * @param errorStream
+ * Error stream to pipe program error input to.
+ * May be <code>null</code>,
+ * in this case error input from the program is discarded.
+ */
+ public void pipeError(OutputStream errorStream) {
+ if (dataError != null) {
+ dataError = null;
+ targetError = errorStream;
+ doPipeError();
+ }
+ }
+
+ /**
+ * Creates pipe from process error input to target error output.
+ */
+ private void doPipeError() {
+ new StreamPipe(processError, targetError).start();
+ }
+
+ /**
+ * Waits for subprocess to terminate and returns its exit code.
+ *
+ * @return The subprocess exit code.
+ */
+ public int waitFor() {
+ while (true) {
+ try {
+ return process.waitFor();
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ /**
+ * Destroys this subprocess.
+ */
+ public void destroy() {
+ process.destroy();
+ dataInput = null;
+ dataOutput = null;
+ dataError = null;
+ }
+
+ /**
+ * Writes the {@linkplain #READY_STRING default "ready" string}
+ * to the process output stream.
+ *
+ * @throws IllegalStateException
+ * If subprocess output stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void tell() throws IllegalStateException, IOException {
+ tell(READY_STRING);
+ }
+
+ /**
+ * Writes the specified string to the process output stream.
+ *
+ * @param str
+ * String to write.
+ *
+ * @throws IllegalStateException
+ * If subprocess output stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void tell(String str) throws IllegalStateException, IOException {
+ if (dataOutput == null) {
+ throw new IllegalStateException(
+ "Subprocess output stream control disabled");
+ }
+ tell(dataOutput, str);
+ }
+
+ /**
+ * Writes the {@linkplain #READY_STRING default "ready" string}
+ * to the {@linkplain System#out system output stream}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void tellOut() throws IOException {
+ tellOut(READY_STRING);
+ }
+
+ /**
+ * Writes the specified string to the
+ * {@linkplain System#out system output stream}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @param str
+ * String to write.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void tellOut(String str) throws IOException {
+ tell(new DataOutputStream(System.out), str);
+ }
+
+ /**
+ * Writes the {@linkplain #READY_STRING default "ready" string}
+ * to the {@linkplain System#err system error stream}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void tellError() throws IOException {
+ tellError(READY_STRING);
+ }
+
+ /**
+ * Writes the specified string to the
+ * {@linkplain System#err system error stream}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @param str
+ * String to write.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void tellError(String str) throws IOException {
+ tell(new DataOutputStream(System.err), str);
+ }
+
+ /**
+ * Writes the specified string to the process output stream.
+ *
+ * @param stream
+ * Stream to write the string to.
+ *
+ * @param str
+ * String to write.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ private static void tell(DataOutputStream stream, String str)
+ throws IOException {
+ stream.writeBytes('\n' + str + '\n');
+ stream.flush();
+ }
+
+ /**
+ * Waits until the {@linkplain #READY_STRING default "ready" string}
+ * appears in the program input. Equivalent to
+ * {@link #expect(String, boolean, boolean) expect(READY_STRING, false, false)}.
+ *
+ * @throws IllegalStateException
+ * If subprocess input stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expect() throws IllegalStateException, IOException {
+ expect(READY_STRING);
+ }
+
+ /**
+ * Waits until the specified string appears in the program input.
+ * Equivalent to
+ * {@link #expect(String, boolean, boolean) expect(str, false, false)}.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @throws IllegalStateException
+ * If subprocess input stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expect(String str) throws IllegalStateException, IOException {
+ expect(str, false, false);
+ }
+
+ /**
+ * Waits until the specified string appears in the program input.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @param whole
+ * If <code>true</code>, the whole input lines are compared
+ * to the specified string, otherwise the string is considered
+ * to be found if it appears as a substring in any input line.
+ *
+ * @param ignoreCase
+ * If <code>true</code>, case-insensitive comparison is performed.
+ *
+ * @throws IllegalStateException
+ * If subprocess input stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expect(String str, boolean whole, boolean ignoreCase)
+ throws IllegalStateException, IOException {
+ if (dataInput == null) {
+ throw new IllegalStateException(
+ "Subprocess input stream control disabled");
+ }
+ expect(dataInput, str, whole, ignoreCase);
+ }
+
+ /**
+ * Waits until the {@linkplain #READY_STRING default "ready" string}
+ * appears in the program error input. Equivalent to
+ * {@link #expectError(String, boolean, boolean) expectError(READY_STRING, false, false)}.
+ *
+ * @throws IllegalStateException
+ * If subprocess error stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expectError() throws IllegalStateException, IOException {
+ expectError(READY_STRING);
+ }
+
+ /**
+ * Waits until the specified string appears in the program error input.
+ * Equivalent to
+ * {@link #expectError(String, boolean, boolean) expectError(str, false, false)}.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @throws IllegalStateException
+ * If subprocess error stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expectError(String str)
+ throws IllegalStateException, IOException {
+ expectError(str, false, false);
+ }
+
+ /**
+ * Waits until the specified string appears in the program error input.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @param whole
+ * If <code>true</code>, the whole input lines are compared
+ * to the specified string, otherwise the string is considered
+ * to be found if it appears as a substring in any input line.
+ *
+ * @param ignoreCase
+ * If <code>true</code>, case-insensitive comparison is performed.
+ *
+ * @throws IllegalStateException
+ * If subprocess error stream control is disabled.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public void expectError(String str, boolean whole, boolean ignoreCase)
+ throws IllegalStateException, IOException {
+ if (dataError == null) {
+ throw new IllegalStateException(
+ "Subprocess error stream control disabled");
+ }
+ expect(dataError, str, whole, ignoreCase);
+ }
+
+ /**
+ * Waits until the {@linkplain #READY_STRING default "ready" string}
+ * appears in {@linkplain System#in system input stream}. Equivalent to
+ * {@link #expectIn(String, boolean, boolean) expectIn(READY_STRING, false, false)}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void expectIn() throws IOException {
+ expectIn(READY_STRING);
+ }
+
+ /**
+ * Waits until the specified string appears in
+ * {@linkplain System#in system input stream}.
+ * Equivalent to {@link #expectIn(String, boolean, boolean) expectIn(str, false, false)}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void expectIn(String str) throws IOException {
+ expectIn(str, false, false);
+ }
+
+ /**
+ * Waits until the specified string appears in
+ * {@linkplain System#in system input stream}.
+ *
+ * This static method is usable by child subprocesses
+ * for communication with the parent process.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @param whole
+ * If <code>true</code>, the whole input lines are compared
+ * to the specified string, otherwise the string is considered
+ * to be found if it appears as a substring in any input line.
+ *
+ * @param ignoreCase
+ * If <code>true</code>, case-insensitive comparison is performed.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ public static void expectIn(String str, boolean whole, boolean ignoreCase)
+ throws IOException {
+ expect(new DataInputStream(System.in), str, whole, ignoreCase);
+ }
+
+ /**
+ * Waits until the specified string appears in the specified stream.
+ *
+ * @param stream
+ * Stream to wait for the string in.
+ *
+ * @param str
+ * String to wait for.
+ *
+ * @param whole
+ * If <code>true</code>, the whole input lines are compared
+ * to the specified string, otherwise the string is considered
+ * to be found if it appears as a substring in any input line.
+ *
+ * @param ignoreCase
+ * If <code>true</code>, case-insensitive comparison is performed.
+ *
+ * @throws IOException
+ * If I/O error occurs.
+ */
+ private static void expect(DataInputStream stream, String str,
+ boolean whole, boolean ignoreCase) throws IOException {
+ if (ignoreCase && !whole) {
+ str = str.toLowerCase();
+ }
+
+ while (true) {
+ String line = stream.readLine();
+
+ if (line == null) {
+ // End of stream
+ throw new EOFException();
+ }
+
+ if (whole ? (ignoreCase ? line.equalsIgnoreCase(str)
+ : line.equals(str))
+ : ((ignoreCase ? line.toLowerCase()
+ : line).indexOf(str) >= 0)) {
+ // expectString is found
+ return;
+ }
+ }
+ }
+
+ /**
+ * Automatically transfers data from input to output stream
+ * using new thread.
+ *
+ * Use {@link #start()} method to start the transferring thread.
+ * The thread terminates itself when end of input stream is encountered.
+ */
+ private final class StreamPipe extends Thread {
+
+ /**
+ * Input stream.
+ */
+ private InputStream input;
+
+ /**
+ * Output stream.
+ */
+ private OutputStream output;
+
+ /**
+ * Constructs this object.
+ *
+ * @param input
+ * Input stream to read data from.
+ *
+ * @param output
+ * Output stream to write data to.
+ * Can be <code>null</code>, in this case data are just read
+ * from <code>input</code> stream and discarded.
+ */
+ StreamPipe(InputStream input, OutputStream output) {
+ this.input = input;
+ this.output = output;
+ setDaemon(true);
+ }
+
+ /**
+ * Runs this thread, called by VM.
+ */
+ public void run() {
+ try {
+ byte[] buffer = new byte[1024];
+ int len;
+
+ /*
+ * Checking the streams' state seems to be unnecessary,
+ * as soon as the thread is a daemon thread,
+ * and will also exit at first error in either stream.
+ */
+ while ((len = input.read(buffer)) > 0) {
+ if (output != null) {
+ output.write(buffer, 0, len);
+ output.flush();
+ }
+ }
+ assert (len == -1)
+ : ("read(byte[]) returned unexpected value: " + len);
+ } catch (IOException e) {
+ System.err.print("StreamPipe error: ");
+ e.printStackTrace();
+ }
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/SubProcess.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/package.html
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/package.html?rev=407625&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/package.html (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/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 common implementation classes.
+</body>
+</html>
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/rmi3/src/common/javasrc/org/apache/harmony/rmi/common/package.html
------------------------------------------------------------------------------
svn:eol-style = native