blob: 4879d2465ea59260efc70597d03364b1d3fca607 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
* $RCSfile: ExpressionCommands.java,v $
* $Revision: 1.8 $ $Date: 2005/08/24 20:39:08 $
*/
package org.eclipse.jem.internal.proxy.common.remote;
import java.io.*;
import org.eclipse.jem.internal.proxy.common.CommandException;
/**
*
* @since 1.0.0
*/
public class ExpressionCommands {
// These are the sub-commands under EXPRESSION_TREE_COMMANDS that can be send.
public static final byte
START_EXPRESSION_TREE_PROCESSING = 0,
PUSH_EXPRESSION = 1,
END_EXPRESSION_TREE_PROCESSING = 2,
SYNC_REQUEST = 3,
PULL_VALUE_REQUEST = 4,
TRANSFER_EXPRESSION_REQUEST = 5,
RESUME_EXPRESSION_REQUEST = 6;
// These are the expression specific error codes (it can also send back general ones. See SYNC_REQUEST docs lower down).
public static final int
EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION = Commands.MAX_ERROR_CODE+1; // No expression value occurred.
// These are the flag values sent in proxy resolution when doesn't resolve to proxy.
public static final int
EXPRESSIONPROXY_VOIDTYPE = 0, // Expression proxy resolves to void type.
EXPRESSIONPROXY_NOTRESOLVED = 1; // Expression proxy not resolved.
// These are the trace values sent in START_EXPRESSION_TREE_PROCESSING
public static final byte
TRACE_DEFAULT = -1,
TRACE_OFF = 0,
TRACE_ON = 1;
public static final String EXPRESSIONTRACE = "proxyvm.expressionTrace"; // The system property for turning on expression tracing. //$NON-NLS-1$
public static final String EXPRESSIONTRACE_TIMER_THRESHOLD = "proxyvm.expressionTraceTimerThreshold"; // The system property for timer threshold. //$NON-NLS-1$
/*
* The format of the commands are:
* Note: Most of the commands will not being doing a os.flush() at the end. We are just going to
* be streaming the data over the line. At the end we will flush and then catch up. That way
* we aren't waiting for the other side as we send the data.
*
* START_EXPRESSION_TREE_PROCESSING: 0b, trace
* Start processing.
* byte(trace): -1 : do default
* 0 : no trace
* 1 : do trace
*
* PUSH_EXPRESSION: 1b, b
* Push an expression. Where "b" is the expression type from IInternalExpressionConstants.
* The actual data that follows is expression type dependent and will be
* sent in a following call to ExpressionCommands as it builds up the actual command.
* See REMExpression and each type of push call method within it to see the actual
* sent data.
*
* END_EXPRESSION_TREE_PROCESSING: 2b
* End the processing and clean up.
*
* SYNC_REQUEST: 3b
* This will return the current status. The reason it is called sync is because the
* IDE will wait for it to complete and read back the value. It will send back:
* 1: VALUE command with boolean true as the value.
* 2: ERROR command with code of ExpressionClassNotFound, with value of String with message from exception.
* 3: ERROR command with code of EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, with value of String with message from exception.
* 4: THROWABLE command with the actual exception that occurred.
*
*
* PULL_VALUE_REQUEST: 4b
* This will do a sync up and return the value from the expression.
* IDE will wait for it to compleate and read back the value. It will send back:
* 1: VALUE command with the result as the value.
* 2: ERROR or EXCEPTION if there were errors, see SYNC_REQUEST with the format they are sent back.
*
* TRANSFER_EXPRESSION_REQUEST: 5b
* This will do a sync up, and return the ExpressionProcessorController that the request is for. And remove
* the controller from its list of active expression controllers.
*
* RESUME_EXPRESSION_REQUEST: 6b, anExpressionProcessorController
* This will take the given controller and add it to the list of controllers this connection is handling. It returns nothing.
*
* @see org.eclipse.jem.internal.proxy.initParser.tree.IInternalExpressionConstants
* @see org.eclipse.jem.internal.proxy.remote.REMExpression
*
*/
/**
* Send the start expression processing command.
* @param expressionID
* @param trace
* @param os
*
* @throws IOException
*
* @since 1.0.0
*/
public static void sendStartExpressionProcessingCommand(int expressionID, byte trace, DataOutputStream os) throws IOException {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(START_EXPRESSION_TREE_PROCESSING);
os.writeByte(trace);
}
/**
* Send the end expression processing command.
* @param expressionID
* @param os
*
* @throws IOException
*
* @since 1.0.0
*/
public static void sendEndExpressionProcessingCommand(int expressionID, DataOutputStream os) throws IOException {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(END_EXPRESSION_TREE_PROCESSING);
os.flush(); // Flushing because we are done and want to make sure everything goes out.
}
/**
* Send an expression subcommand.
* @param expressionID
* @param os
* @param subcommand
*
* @throws IOException
*
* @since 1.0.0
*/
public static void sendExpressionCommand(int expressionID, DataOutputStream os, byte subcommand) throws IOException {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(PUSH_EXPRESSION);
os.writeByte(subcommand);
}
/**
* Send just a byte.
*
* @param os
* @param aByte
* @throws IOException
*
* @since 1.0.0
*/
public static void sendByte(DataOutputStream os, byte aByte) throws IOException {
os.writeByte(aByte);
}
/**
* Send just an int.
*
* @param os
* @param anInt
* @throws IOException
*
* @since 1.0.0
*/
public static void sendInt(DataOutputStream os, int anInt) throws IOException {
os.writeInt(anInt);
}
/**
* Send just a string.
*
* @param os
* @param aString
* @throws IOException
*
* @since 1.0.0
*/
public static void sendString(DataOutputStream os, String aString) throws IOException {
Commands.sendStringData(os, aString);
}
/**
* Send just a boolean.
*
* @param os
* @param aBool
* @throws IOException
*
* @since 1.0.0
*/
public static void sendBoolean(DataOutputStream os, boolean aBool) throws IOException {
os.writeBoolean(aBool);
}
/**
* Send the pull value command. After processing the proxies, caller should call getFinalValue() to get the value.
* @param expressionID
* @param os
* @param is
* @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
* @param sender sender used to process the resolved proxy ids, or <code>null</code> if no proxy ids.
* @throws CommandException
*
* @since 1.0.0
*/
public static void sendPullValueCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(PULL_VALUE_REQUEST);
sendProxyIDs(os, proxyids);
os.flush();
if (proxyids != null) {
Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS); // Read the array header.
sender.initialize(proxyids);
Commands.readArray(is, proxyids.anInt, sender, proxyids, true); // Read the array.
}
} catch (CommandException e) {
// rethrow this exception since we want these to go on out.
throw e;
} catch (IOException e) {
// Wrapper this one.
throw new UnexpectedExceptionCommandException(false, e);
}
}
/**
* Send a sync command. This does a synchronize with the remote expression processor. It makes sure that the
* stream is caught and doesn't return until everything on the stream has been processed. Should then call
* getFinalValue() to verify the expression is valid.
* @param expressionID
* @param os
* @param is
* @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
* @param sender the sender used for reading back the proxyid resolutions, or <code>null</code> if no proxy ids.
*
* @throws CommandException
*
* @since 1.0.0
*/
public static void sendSyncCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(SYNC_REQUEST);
sendProxyIDs(os, proxyids);
os.flush();
if (proxyids != null) {
Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS); // Read the array header.
sender.initialize(proxyids);
Commands.readArray(is, proxyids.anInt, sender, proxyids, true); // Read the array.
}
} catch (CommandException e) {
// rethrow this exception since we want these to go on out.
throw e;
} catch (Exception e) {
// Wrapper this one.
throw new UnexpectedExceptionCommandException(false, e);
}
}
/**
* Send the proxyids (if not null) as part of a command. Used by sync and pullValue.
* @param os
* @param proxyids <code>null</code> if not requesting proxy ids.
* @throws IOException
* @throws CommandException
*
* @since 1.1.0
*/
private static void sendProxyIDs(DataOutputStream os, Commands.ValueObject proxyids) throws IOException, CommandException {
if (proxyids != null) {
os.writeBoolean(true); // Indicates proxy ids being sent.
Commands.writeValue(os, proxyids, false, false);
} else
os.writeBoolean(false); // No proxyids being sent.
}
/**
* Send the transfer expression command and receive back the expression processor controller.
*
* @param expressionID
* @param os
* @param is
* @param expressionProcesserController
* @throws CommandException
*
* @since 1.1.0
*/
public static void sendTransferExpressionCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject expressionProcesserController) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(TRANSFER_EXPRESSION_REQUEST);
os.flush();
Commands.readBackValue(is, expressionProcesserController, Commands.NO_TYPE_CHECK); // Read the expression processor controller
} catch (CommandException e) {
throw e;
} catch (Exception e) {
// Wrapper this one.
throw new UnexpectedExceptionCommandException(false, e);
}
}
/**
* Send the resume expression command with given expression processor controller.
*
* @param expressionID
* @param os
* @param expressionProcessorController
* @throws CommandException
*
* @since 1.1.0
*/
public static void sendResumeExpressionCommand(int expressionID, DataOutputStream os, Commands.ValueObject expressionProcessorController) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(RESUME_EXPRESSION_REQUEST);
Commands.writeValue(os, expressionProcessorController, false, false);
} catch (CommandException e) {
throw e;
} catch (Exception e) {
// Wrapper this one.
throw new UnexpectedExceptionCommandException(false, e);
}
}
private ExpressionCommands() {
// Never intended to be instantiated.
}
}