diff options
Diffstat (limited to 'plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java')
-rw-r--r-- | plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java | 926 |
1 files changed, 0 insertions, 926 deletions
diff --git a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java deleted file mode 100644 index d7780b913..000000000 --- a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java +++ /dev/null @@ -1,926 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 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 - *******************************************************************************/ -package org.eclipse.jem.internal.proxy.vm.remote; -/* - * $RCSfile: ConnectionHandler.java,v $ - * $Revision: 1.16 $ $Date: 2005/12/02 18:41:25 $ - */ - - -import java.io.*; -import java.lang.reflect.Array; -import java.net.Socket; -import java.net.SocketException; -import java.util.*; - -import org.eclipse.jem.internal.proxy.common.CommandException; -import org.eclipse.jem.internal.proxy.common.remote.*; -import org.eclipse.jem.internal.proxy.initParser.*; -import org.eclipse.jem.internal.proxy.initParser.tree.NoExpressionValueException; - -/** - * This handles one connection. - */ - -public class ConnectionHandler { - - protected Socket socket; - final protected RemoteVMServerThread server; - final protected Thread connectionThread; - protected DataInputStream in; - protected DataOutputStream out; - - // Kludge: Bug in Linux 1.3.xxx of JVM. Closing a socket while the socket is being read/accept will not interrupt the - // wait. Need to timeout to the socket read/accept before the socket close will be noticed. This has been fixed - // in Linux 1.4. So on Linux 1.3 need to put timeouts in on those sockets that can be separately closed while reading/accepting. - static boolean LINUX_1_3 = "linux".equalsIgnoreCase(System.getProperty("os.name")) && System.getProperty("java.version","").startsWith("1.3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - - /** - * This may be running as a callback, in that case there is no connectionThread. - */ - public ConnectionHandler(Socket sc, RemoteVMServerThread svr, Thread connectionThread) { - socket = sc; - server = svr; - this.connectionThread = connectionThread; - - Integer bufSize = Integer.getInteger("proxyvm.bufsize"); //$NON-NLS-1$ - if (bufSize == null) - bufSize = new Integer(5000); - - try { - out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), bufSize.intValue())); - in = new DataInputStream(new BufferedInputStream(socket.getInputStream(), bufSize.intValue())); - } catch (IOException e) { - } - - } - - /** - * Did this construct correctly. - * This is needed because an exception could be thrown in the ctor and - * that's not a good thing to do. - */ - public boolean isConnected() { - return socket != null; - } - - /** - * Request the thread to close down. - */ - public void close() { - if (socket != null) { - try { - Socket s = socket; - socket = null; - s.close(); - } catch (Exception e) { - } - } - } - - // Map of ID to expression processers that are currently being processed. - private Map expressionProcessors = new HashMap(); - - /** - * Process and loop until told to stop. A callback_done will stop - * the loop and will return a result. Otherwise null is returned. - */ - public Object run() throws CommandException { - Object result = null; - boolean shutdown = false; - boolean closeWhenDone = true; - Commands.ValueObject valueObject = new Commands.ValueObject(); // Working value object so not continually recreated. - InvokableValueSender valueSender = new InvokableValueSender(); // Working valuesender so not continually recreated. - try { - boolean doLoop = true; - - /** - * Note: In the cases below you will see a lot of finally clauses that null variables out. - * This is because this is a long running loop, and variables declared within blocks are not - * garbage collected until the method is terminated, so these variables once set would never - * be GC'd. The nulling at the end of the case makes sure that any of those objects set are - * now available for garbage collection when necessary. - */ - while(doLoop && isConnected()) { - byte cmd = 0; - try { - if (LINUX_1_3) - socket.setSoTimeout(1000); // Linux 1.3 bug, see comment on LINUX_1_3 - cmd = in.readByte(); - if (LINUX_1_3 && isConnected()) - socket.setSoTimeout(0); // Linux 1.3 bug, see comment on LINUX_1_3 - } catch (InterruptedIOException e) { - continue; // Timeout, try again - } - switch (cmd) { - case Commands.QUIT_CONNECTION: - doLoop = false; - break; // Close this connection - - case Commands.TERMINATE_SERVER: - doLoop = false; - shutdown = true; // Shutdown everything - break; - - case Commands.GET_CLASS: - String className = in.readUTF(); - Class aClass = null; - Class superClass = null; - String superClassName = null; - boolean added = false; - try { - aClass = Class.forName(className); // Turns out using JNI format for array type will work fine. - - added = server.getIdentityID(aClass, valueObject); - boolean isInterface = aClass.isInterface(); - boolean isAbstract = java.lang.reflect.Modifier.isAbstract(aClass.getModifiers()); - superClass = aClass.getSuperclass(); - superClassName = (superClass != null) ? superClass.getName() : ""; //$NON-NLS-1$ - out.writeByte(Commands.GET_CLASS_RETURN); - out.writeInt(valueObject.objectID); - out.writeBoolean(isInterface); - out.writeBoolean(isAbstract); - out.writeUTF(superClassName); - out.flush(); - } catch (ClassNotFoundException e) { - valueObject.set(); - Commands.sendErrorCommand(out, Commands.GET_CLASS_NOT_FOUND, valueObject); - } catch (ExceptionInInitializerError e) { - sendException(e.getException(), valueObject, out); - } catch (LinkageError e) { - sendException(e, valueObject, out); - } catch (Throwable e) { - // Something bad, did we add a class? If we did remove it from the table. - if (added) - server.removeObject(server.getObject(valueObject.objectID)); - throw e; - } finally { - // clear out for GC to work. - className = null; - aClass = null; - superClass = null; - superClassName = null; - valueObject.set(); - } - break; - - case Commands.GET_CLASS_FROM_ID: - int classID = in.readInt(); - try { - aClass = (Class) server.getObject(classID); - boolean isInterface = aClass.isInterface(); - boolean isAbstract = java.lang.reflect.Modifier.isAbstract(aClass.getModifiers()); - superClass = aClass.getSuperclass(); - superClassName = (superClass != null) ? superClass.getName() : ""; //$NON-NLS-1$ - out.writeByte(Commands.GET_CLASS_ID_RETURN); - out.writeUTF(aClass.getName()); - out.writeBoolean(isInterface); - out.writeBoolean(isAbstract); - out.writeUTF(superClassName); - out.flush(); - } catch (ClassCastException e) { - valueObject.set(); - Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject); - } finally { - // clear out for GC to work. - aClass = null; - superClass = null; - superClassName = null; - valueObject.set(); - } - break; - - case Commands.GET_OBJECT_DATA: - int objectID = in.readInt(); - Object anObject = null; - try { - anObject = server.getObject(objectID); - valueObject.setObjectID(objectID, server.getIdentityID(anObject.getClass())); - Commands.writeValue(out, valueObject, true); - } catch (ClassCastException e) { - valueObject.set(); - Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject); - } finally { - anObject = null; // Clear out for GC to work - valueObject.set(); - } - break; - - case Commands.RELEASE_OBJECT: - int id = in.readInt(); - server.removeObject(server.getObject(id)); - break; - - case Commands.NEW_INIT_STRING: - classID = in.readInt(); // ID Of class to do new upon. - String initString = in.readUTF(); // The init string. - Object newValue = null; - Class theClass = null; - try { - theClass = (Class) server.getObject(classID); - if (theClass == null) { - // The class wasn't found. So imply ClassNotFound exception. - throw new ClassNotFoundException(); - } - - InitializationStringParser parser = null; - try { - parser = InitializationStringParser.createParser(initString); - newValue = parser.evaluate(); - boolean primitive = parser.isPrimitive(); - // If expected class is Void.TYPE, that means don't test the type of the result - // to verify if correct type, just return what it really is. - if (theClass != Void.TYPE && primitive != theClass.isPrimitive()) { - valueObject.set(); - Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject); - continue; // Goto next command. - } - if (primitive) { - try { - // Need to do special tests for compatibility and assignment. - sendObject(newValue, classID != Commands.VOID_TYPE ? classID : server.getIdentityID(parser.getExpectedType()), valueObject, out, true); // This will make sure it goes out as the correct primitive type - } catch (ClassCastException e) { - // The returned type is not of the correct type for what is expected. - valueObject.set(); - Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject); - continue; // Goto next command - } - } else { - if (newValue != null) { - // Test to see if they are compatible. (Null can be assigned to any object, - // so that is why it was tested out above). - // If expected class is Void.TYPE, that means don't test the type of the result - // to verify if correct type, just return what it really is. - if (theClass != Void.TYPE && !theClass.isInstance(newValue)) { - // The returned type is not of the correct type for what is expected. - valueObject.set(); - Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject); - continue; // Goto next command - } - } - sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true); // Send out as an object. - } - } catch (InitializationStringEvaluationException e) { - if (e instanceof EvaluationException) { - // Want to return the real exception. - sendException(e.getOriginalException(), valueObject, out); - } else { - // Couldn't be evaluated, return an error for this. - setExceptionIntoValue(e.getOriginalException(), valueObject); - Commands.sendErrorCommand(out, Commands.CANNOT_EVALUATE_STRING, valueObject); - } - } finally { - parser = null; // Clear out for GC to work - } - } catch (Throwable e) { - sendException(e, valueObject, out); - } finally { - // Clear out for GC to work - initString = null; - theClass = null; - newValue = null; - valueObject.set(); - } - break; - - case Commands.INVOKE: - Object target = null; - Object[] parms = null; - Class returnType = null; - java.lang.reflect.Method aMethod = null; - try { - int methodID = in.readInt(); // ID of method to invoke - aMethod = (java.lang.reflect.Method) server.getObject(methodID); // Method to invoke - Commands.readValue(in, valueObject); - target = getInvokableObject(valueObject); - Commands.readValue(in, valueObject); - if (valueObject.type == Commands.ARRAY_IDS) { - // It is an array containing IDs, as it normally would be. - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - parms = (Object[]) valueSender.getArray(); - } else { - // It is all objects or null, so it should be an Object[] or null. If not, then this is an error. - parms = (Object[]) valueObject.anObject; - } - - if (!aMethod.isAccessible()) - aMethod.setAccessible(true); // We will allow all to occur. Let access control be handled by IDE and compiler. - newValue = aMethod.invoke(target, parms); - returnType = aMethod.getReturnType(); - if (returnType.isPrimitive()) { - int returnTypeID = server.getIdentityID(returnType); - // Need to tell sendObject the correct primitive type. - sendObject(newValue, returnTypeID, valueObject, out, true); - - } else { - sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true); // Just send the object back. sendObject knows how to iterpret the type - } - } catch (CommandException e) { - throw e; // Throw it again. These we don't want to come up as an exception proxy. These should end the thread. - } catch (java.lang.reflect.InvocationTargetException e) { - // This is a wrappered exception. Return the wrappered one so it looks like - // it was the real one. (Sometimes the method being invoked is on a java.lang.reflect.Constructor.newInstance, - // which in turn is an InvocationTargetException, so we will go until we don't have an InvocationTargetException. - Throwable t = e; - do { - t = ((java.lang.reflect.InvocationTargetException) t).getTargetException(); - } while (t instanceof java.lang.reflect.InvocationTargetException); - sendException(t, valueObject, out); - } catch (Throwable e) { - sendException(e, valueObject, out); // Turn it into a exception proxy on the client. - } finally { - // Clear out for GC to work - valueObject.set(); - parms = null; - target = null; - aMethod = null; - returnType = null; - newValue = null; - valueSender.clear(); - } - break; - - case Commands.INVOKE_WITH_METHOD_PASSED: - aClass = null; - String methodName = null; - Class[] parmTypes = null; - target = null; - parms = null; - returnType = null; - aMethod = null; - - try { - Commands.readValue(in, valueObject); - aClass = (Class) getInvokableObject(valueObject); // The class that has the method. - methodName = in.readUTF(); - Commands.readValue(in, valueObject); - if (valueObject.type == Commands.ARRAY_IDS) { - // It is an array containing IDs, as it normally would be. - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - parmTypes = (Class[]) valueSender.getArray(); - } else { - // It null, so it should be an null. If not, then this is an error. - parmTypes = null; - } - aMethod = aClass.getMethod(methodName, parmTypes); - - // Now we get the info for the invocation of the method and execute it. - Commands.readValue(in, valueObject); - target = getInvokableObject(valueObject); - Commands.readValue(in, valueObject); - if (valueObject.type == Commands.ARRAY_IDS) { - // It is an array containing IDs, as it normally would be. - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - parms = (Object[]) valueSender.getArray(); - } else { - // It is all objects or null, so it should be an Object[] or null. If not, then this is an error. - parms = (Object[]) valueObject.anObject; - } - - if (!aMethod.isAccessible()) - aMethod.setAccessible(true); // We will allow all to occur. Let access control be handled by IDE and compiler. - newValue = aMethod.invoke(target, parms); - returnType = aMethod.getReturnType(); - if (returnType.isPrimitive()) { - int returnTypeID = server.getIdentityID(returnType); - // Need to tell sendObject the correct primitive type. - sendObject(newValue, returnTypeID, valueObject, out, true); - - } else { - sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true); // Just send the object back. sendObject knows how to iterpret the type - } - } catch (CommandException e) { - throw e; // Throw it again. These we don't want to come up as an exception proxy. These should end the thread. - } catch (java.lang.reflect.InvocationTargetException e) { - // This is a wrappered exception. Return the wrappered one so it looks like - // it was the real one. (Sometimes the method being invoked is on a java.lang.reflect.Constructor.newInstance, - // which in turn is an InvocationTargetException, so we will go until we don't have an InvocationTargetException. - Throwable t = e; - do { - t = ((java.lang.reflect.InvocationTargetException) t).getTargetException(); - } while (t instanceof java.lang.reflect.InvocationTargetException); - sendException(t, valueObject, out); - - } catch (Throwable e) { - sendException(e, valueObject, out); // Turn it into a exception proxy on the client. - } finally { - aClass = null; - methodName = null; - parmTypes = null; - // Clear out for GC to work - valueObject.set(); - parms = null; - target = null; - aMethod = null; - returnType = null; - newValue = null; - valueSender.clear(); - } - break; - - case Commands.GET_ARRAY_CONTENTS: - try { - target = server.getObject(in.readInt()); // Array to get the ids for. - valueObject.setArrayIDS(new ArrayContentsRetriever(target), Array.getLength(target), Commands.OBJECT_CLASS); - Commands.writeValue(out, valueObject, true); // Write it back as a value command. - } catch (CommandException e) { - throw e; // Throw it again. These we don't want to come up as an exception proxy. These should end the thread. - } catch (Throwable e) { - sendException(e, valueObject, out); // Turn it into a exception proxy on the client. - } finally { - target = null; - valueObject.set(); - } - break; - - case Commands.CALLBACK_DONE: - try { - if (connectionThread != null) { - valueObject.set(); - Commands.sendErrorCommand(out, Commands.UNKNOWN_COMMAND_SENT, valueObject); - } else { - try { - Commands.readBackValue(in, valueObject, Commands.NO_TYPE_CHECK); - if (valueObject.type == Commands.ARRAY_IDS) { - // It is an array containing IDs, as it normally would be. - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - result = valueSender.getArray(); - } else { - result = getInvokableObject(valueObject); - } - doLoop = false; // We need to terminate and return result - closeWhenDone = false; // Don't close, we will continue. - } catch (CommandErrorException e) { - // There was an command error on the other side. This means - // connection still good, but don't continue the callback processing. - doLoop = false; // We need to terminate and return result - closeWhenDone = false; // Don't close, we will continue. - throw e; // Let it go on out. - } - } - } finally { - valueObject.set(); - valueSender.clear(); - } - break; - - case Commands.ERROR: - try { - // Got an error command. Don't know what to do but read the - // value and simply print it out. - Commands.readValue(in, valueObject); - result = getInvokableObject(valueObject); - System.out.println("Error sent to server: Result=" + result); //$NON-NLS-1$ - } finally { - valueObject.set(); - } - break; - - case Commands.EXPRESSION_TREE_COMMAND: - try { - processExpressionCommand(valueObject, valueSender); - } finally { - valueObject.set(); - valueSender.clear(); - } - break; - - default: - // Unknown command. We don't know how long it is, so we need to shut the connection down. - System.err.println("Error: Invalid cmd send to server: Cmd=" + cmd); //$NON-NLS-1$ - doLoop = false; - closeWhenDone = true; - break; - } - } - } catch (EOFException e) { - // This is ok. It means that the connection on the other side was terminated. - // So just accept this and go down. - } catch (CommandException e) { - throw e; - } catch (SocketException e) { - if (socket != null) - throw new UnexpectedExceptionCommandException(false, e); // socket null means a valid close request - } catch (Throwable e) { - e.printStackTrace(); - } finally { - if (closeWhenDone) { - try { - for (Iterator itr = expressionProcessors.values().iterator(); itr.hasNext();) { - ExpressionProcesserController exp = (ExpressionProcesserController) itr.next(); - exp.close(); - } - } finally { - expressionProcessors.clear(); - } - - if (in != null) - try { - in.close(); - } catch (Exception e) { - } - in = null; - if (out != null) - try { - out.close(); - } catch (Exception e) { - } - out = null; - close(); - } - } - - if (closeWhenDone && connectionThread != null) - server.removeConnectionThread(connectionThread); - if (shutdown) - server.requestShutdown(); - - return result; - } - - // A retriever is what handles the array get contents. - private class ArrayContentsRetriever implements Commands.ValueRetrieve { - int index=0; - Object array; - int length; - int componentType; - Commands.ValueObject worker = new Commands.ValueObject(); - - - public ArrayContentsRetriever(Object anArray) { - array = anArray; - length = Array.getLength(anArray); - if (anArray.getClass().getComponentType().isPrimitive()) { - componentType = server.getIdentityID(anArray.getClass().getComponentType()); - } else - componentType = NOT_A_PRIMITIVE; - } - - public Commands.ValueObject nextValue() { - fillInValue(Array.get(array, index++), componentType, worker); - return worker; - } - }; - - - private void processExpressionCommand(Commands.ValueObject valueObject, InvokableValueSender valueSender) throws IOException, CommandException { - Integer expressionID = new Integer(in.readInt()); - byte cmdType = in.readByte(); - ExpressionProcesserController exp = null; - switch (cmdType) { - case ExpressionCommands.START_EXPRESSION_TREE_PROCESSING: - byte trace = in.readByte(); - if (trace == ExpressionCommands.TRACE_DEFAULT) - exp = new ExpressionProcesserController(server, this); - else - exp = new ExpressionProcesserController(server, this, trace == ExpressionCommands.TRACE_ON); - expressionProcessors.put(expressionID, exp); - break; - case ExpressionCommands.TRANSFER_EXPRESSION_REQUEST: - exp = (ExpressionProcesserController) expressionProcessors.remove(expressionID); - sendObject(exp, NOT_A_PRIMITIVE, valueObject, out, true); - break; - case ExpressionCommands.RESUME_EXPRESSION_REQUEST: - Commands.readValue(in, valueObject); - exp = (ExpressionProcesserController) getInvokableObject(valueObject); - expressionProcessors.put(expressionID, exp); - break; - case ExpressionCommands.PUSH_EXPRESSION: - exp = (ExpressionProcesserController) expressionProcessors.get(expressionID); - exp.process(in); - break; - case ExpressionCommands.SYNC_REQUEST: - boolean haveProxies = in.readBoolean(); // See if we expression proxy ids that need to be resolved - if (haveProxies) { - Commands.readValue(in, valueObject); - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - } - - exp = (ExpressionProcesserController) expressionProcessors.get(expressionID); - if (haveProxies) - sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp); - if (exp.noErrors()) { - valueObject.set(true); // Mark that all is good. - Commands.writeValue(out, valueObject, true, true); - } else { - processExpressionError(exp, valueObject); - } - break; - case ExpressionCommands.PULL_VALUE_REQUEST: - haveProxies = in.readBoolean(); // See if we expression proxy ids that need to be resolved - if (haveProxies) { - Commands.readValue(in, valueObject); - valueSender.initialize(valueObject); - Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false); - } - - exp = (ExpressionProcesserController) expressionProcessors.get(expressionID); - if (haveProxies) - sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp); - if (exp.noErrors()) { - try { - Object[] pulledValue = exp.pullValue(); - // Send back the command code for pull value. Don't flush. We will flush when all done. - if (((Class) pulledValue[1]).isPrimitive()) { - int returnTypeID = server.getIdentityID(pulledValue[1]); - // Need to tell sendObject the correct primitive type. - sendObject(pulledValue[0], returnTypeID, valueObject, out, true, true); - - } else { - sendObject(pulledValue[0], NOT_A_PRIMITIVE, valueObject, out, true, true); // Just send the object back. sendObject knows how to iterpret the type - } - } catch (NoExpressionValueException e) { - sendNoValueErrorCommand(exp, valueObject); - } - } else - processExpressionError(exp, valueObject); - break; - case ExpressionCommands.END_EXPRESSION_TREE_PROCESSING: - exp = (ExpressionProcesserController) expressionProcessors.remove(expressionID); - exp.close(); - break; - } - } - - /* - * @param is - * @param exp - * - * @since 1.1.0 - */ - private void sendExpressionProxyResolutions(Commands.ValueObject valueObject, final int[] proxyIDs, final ExpressionProcesserController exp) throws CommandException { - class ExpressionProxyRetriever implements Commands.ValueRetrieve { - int index = 0; - Object[] proxyResolution = new Object[2]; - Commands.ValueObject worker = new Commands.ValueObject(); - - public Commands.ValueObject nextValue() { - int proxyID = proxyIDs[index++]; - if (exp.pullExpressionProxyValue(proxyID, proxyResolution)) { - if (proxyResolution[1] != Void.TYPE) { - if (((Class) proxyResolution[1]).isPrimitive()) { - int returnTypeID = server.getIdentityID(proxyResolution[1]); - // Need to tell worker the correct primitive type. - fillInValue(proxyResolution[0], returnTypeID, worker); - } else { - fillInValue(proxyResolution[0], NOT_A_PRIMITIVE, worker); - } - } else - worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_VOIDTYPE); // It was resolved, but to not set due to void type of expression. - } else - worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_NOTRESOLVED); // It wasn't resolved. - - return worker; - } - }; - - valueObject.setArrayIDS(new ExpressionProxyRetriever(), proxyIDs.length, Commands.OBJECT_CLASS); - Commands.writeValue(out, valueObject, true, false); // Write it back as a value command. - - } - - private void processExpressionError(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException { - if (exp.isNoExpressionValue()) { - sendNoValueErrorCommand(exp, valueObject); - } else - sendException(exp.getErrorThrowable(), valueObject, out); - } - - /* - * @param exp - * @param valueObject - * @throws CommandException - * - * @since 1.1.0 - */ - private void sendNoValueErrorCommand(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException { - setExceptionIntoValue(exp.getErrorThrowable(), valueObject); - Commands.sendErrorCommand(out, ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, valueObject); - } - -protected static final int NOT_A_PRIMITIVE = Commands.NOT_AN_ID; -protected static final int SEND_AS_IS = -2; // This means sends as an object not as an id. - -public static final int CLASS_ADDED = 1; -public static final int OBJECT_ADDED = 2; -public int fillInValue(Object object, int primitiveTypeID, Commands.ValueObject valueObject) { - int added = 0; - if (object == null) { - valueObject.set(); - } else { - int classID = 0; - if (primitiveTypeID != NOT_A_PRIMITIVE && primitiveTypeID != SEND_AS_IS) { - classID = primitiveTypeID; // The object is really supposed to be a primitive of this type - switch (classID) { - case Commands.BOOLEAN_TYPE: - valueObject.set(((Boolean) object).booleanValue()); - break; - case Commands.INTEGER_TYPE: - if (object instanceof Character) - valueObject.set((int) ((Character) object).charValue()); // Because char can be widened to an int - else - valueObject.set(((Number) object).intValue()); - break; - case Commands.BYTE_TYPE: - valueObject.set(((Number) object).byteValue()); - break; - case Commands.CHARACTER_TYPE: - valueObject.set(((Character) object).charValue()); - break; - case Commands.DOUBLE_TYPE: - if (object instanceof Character) - valueObject.set((double) ((Character) object).charValue()); // Because char can be widened to a double - else - valueObject.set(((Number) object).doubleValue()); - break; - case Commands.FLOAT_TYPE: - if (object instanceof Character) - valueObject.set((float) ((Character) object).charValue()); // Because char can be widened to a float - else - valueObject.set(((Number) object).floatValue()); - break; - case Commands.SHORT_TYPE: - valueObject.set(((Number) object).shortValue()); - break; - case Commands.LONG_TYPE: - if (object instanceof Character) - valueObject.set((long) ((Character) object).charValue()); // Because char can be widened to a long - else - valueObject.set(((Number) object).longValue()); - break; - } - } else { - // It's not a primitive. - boolean addObject = false, addClass = false; - Class objClass = object.getClass(); - classID = server.getIdentityID(objClass); - if (classID == RemoteVMServerThread.ID_NOT_FOUND) { - Commands.ValueObject classValue = new Commands.ValueObject(); - addClass = server.getIdentityID(objClass, classValue); - if (addClass) - added |= CLASS_ADDED; - classID = classValue.objectID; - } - - switch (classID) { - case Commands.BYTE_CLASS: - valueObject.set((Byte) object); - break; - case Commands.CHARACTER_CLASS: - valueObject.set((Character) object); - break; - case Commands.DOUBLE_CLASS: - valueObject.set((Double) object); - break; - case Commands.FLOAT_CLASS: - valueObject.set((Float) object); - break; - case Commands.INTEGER_CLASS: - valueObject.set((Integer) object); - break; - case Commands.LONG_CLASS: - valueObject.set((Long) object); - break; - case Commands.SHORT_CLASS: - valueObject.set((Short) object); - break; - case Commands.BOOLEAN_CLASS: - valueObject.set((Boolean) object); - break; - case Commands.STRING_CLASS: - valueObject.set((String) object); - break; - case Commands.BIG_DECIMAL_CLASS: - valueObject.set(object, Commands.BIG_DECIMAL_CLASS); - break; - case Commands.BIG_INTEGER_CLASS: - valueObject.set(object, Commands.BIG_INTEGER_CLASS); - break; - default: - if (primitiveTypeID != SEND_AS_IS) { - addObject = server.getIdentityID(object, valueObject); - if (addObject) { - added |= OBJECT_ADDED; - valueObject.setObjectID(valueObject.objectID, classID); - } else - valueObject.setObjectID(valueObject.objectID); - } else - valueObject.set(object, classID); - break; - } - } - } - - return added; -} - -public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand) throws CommandException { - sendObject(object, primitiveTypeID, valueObject, out, writeAsCommand, writeAsCommand); -} -public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand, boolean flush) throws CommandException { - int added = fillInValue(object, primitiveTypeID, valueObject); - boolean sent = false; - try { - Commands.writeValue(out, valueObject, writeAsCommand, flush); // Write it back as a value command. - sent = true; - } finally { - if (!sent) { - // Ending due to some problem, so clean up any added objects from the id table. - if ((added & OBJECT_ADDED) != 0) - server.removeObject(valueObject.objectID); - if ((added & CLASS_ADDED) != 0) - server.removeObject(valueObject.classID); - } - } -} - - - public void sendException(Throwable e, Commands.ValueObject value, DataOutputStream out) throws CommandException { - // Exception ocurred, return a value command with the exception within it. - setExceptionIntoValue(e, value); - Commands.sendErrorCommand(out, Commands.THROWABLE_SENT, value); - } - - public void setExceptionIntoValue(Throwable e, Commands.ValueObject value) { - server.getIdentityID(e, value); // It should always create it so we don't need to know. - int eID = value.objectID; - Class eClass = e.getClass(); - server.getIdentityID(eClass, value); - int eClassID = value.objectID; - value.setException(eID, eClassID); - } - - /** - * From the valueObject, get an Object that is invokable (i.e. can be the target of an invoke, or one of its parms). - * If it is an array type, the a ValueSender is returned. The invoker needs to then cast this - * to a ValueSender and call the readArray routine. - */ - public Object getInvokableObject(final Commands.ValueObject value) { - switch (value.type) { - case Commands.NEW_OBJECT_ID: - case Commands.OBJECT_ID: - // These need to have access to the server to get the real object - return server.getObject(value.objectID); - default: - // These have all the info needed within the value object itself, so ask it. - return value.getAsObject(); - } - } - - // Helper class for getting an array. - private class InvokableValueSender implements Commands.ValueSender { - int index = 0; - Object array; - - public InvokableValueSender() { - } - - public InvokableValueSender(Commands.ValueObject arrayHeader) { - initialize(arrayHeader); - } - - public void initialize(Commands.ValueObject arrayHeader) { - index = 0; - Class arrayType = (Class) server.getObject(arrayHeader.classID); - array = java.lang.reflect.Array.newInstance(arrayType, arrayHeader.anInt); - } - - public void clear() { - array = null; - index = 0; - } - - public Object getArray() { - return array; - } - - // A new value is being sent to the array - public void sendValue(Commands.ValueObject value) { - java.lang.reflect.Array.set(array, index++, getInvokableObject(value)); // add it to the array - } - - // The next entry is an array too! - public Commands.ValueSender nestedArray(Commands.ValueObject arrayHeader) { - InvokableValueSender sender = new InvokableValueSender(arrayHeader); - // Take the newly created array and put it into the current array. - java.lang.reflect.Array.set(array, index++, sender.getArray()); - return sender; - } - } - -} - - |