/******************************************************************************* * Copyright (c) 2016 Rogue Wave Software, Inc. * 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: * Rogue Wave Software, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.zdb.server.connection; import java.io.DataInputStream; import java.io.IOException; import java.net.URLDecoder; import org.eclipse.che.plugin.zdb.server.connection.ZendDbgClientMessages.GetLocalFileContentResponse; import org.eclipse.che.plugin.zdb.server.connection.ZendDbgClientMessages.IDbgClientResponse; import org.eclipse.che.plugin.zdb.server.utils.ZendDbgConnectionUtils; /** * Zend debug engine messages container. * * @author Bartlomiej Laczkowski */ public class ZendDbgEngineMessages { // Notification types public static final int NOTIFICATION_SRIPT_ENDED = 2002; public static final int NOTIFICATION_READY = 2003; public static final int NOTIFICATION_OUTPUT = 2004; public static final int NOTIFICATION_SESSION_STARTED = 2005; public static final int NOTIFICATION_PARSING_ERROR = 2006; public static final int NOTIFICATION_DEBUGGER_ERROR = 2007; public static final int NOTIFICATION_HEADER_OUTPUT = 2008; public static final int NOTIFICATION_START_PROCESS_FILE = 2009; public static final int NOTIFICATION_INI_ALTERED = 2011; public static final int NOTIFICATION_CLOSE_MESSAGE_HANDLER = 0; // Response types public static final int RESPONSE_START = 1001; public static final int RESPONSE_PAUSE_DEBUGGER = 1002; public static final int RESPONSE_STEP_INTO = 1011; public static final int RESPONSE_STEP_OVER = 1012; public static final int RESPONSE_STEP_OUT = 1013; public static final int RESPONSE_GO = 1014; public static final int RESPONSE_ADD_BREAKPOINT = 1021; public static final int RESPONSE_DELETE_BREAKPOINT = 1022; public static final int RESPONSE_DELETE_ALL_BREAKPOINTS = 1023; public static final int RESPONSE_EVAL = 1031; public static final int RESPONSE_GET_VARIABLE_VALUE = 1032; public static final int RESPONSE_ASSIGN_VALUE = 1033; public static final int RESPONSE_GET_CALL_STACK = 1034; public static final int RESPONSE_GET_STACK_VARIABLE_VALUE = 1035; public static final int RESPONSE_GET_CWD = 1036; public static final int RESPONSE_ADD_FILES = 1038; public static final int RESPONSE_SET_PROTOCOL = 11000; public static final int RESPONSE_UNKNOWN = 1000; // Request types public static final int REQUEST_GET_LOCAL_FILE_CONTENT = 10002; public interface IDbgEngineMessage extends IDbgMessage { /** * De-serialize this debug message from an input stream * * @param in * input stream this message is going to be read from */ public void deserialize(DataInputStream in) throws IOException; } public interface IDbgEngineNotification extends IDbgEngineMessage { } public interface IDbgEngineRequest<T extends IDbgClientResponse> extends IDbgEngineMessage { /** * Return the request id. */ public int getID(); } public interface IDbgEngineResponse extends IDbgEngineMessage { /** * Return the response id. */ public int getID(); /** * Return the response status. */ public int getStatus(); } private static abstract class AbstractEngineRequest<T extends IDbgClientResponse> extends AbstractDbgMessage implements IDbgEngineRequest<T> { private int id; @Override public void deserialize(DataInputStream in) throws IOException { id = in.readInt(); } @Override public int getID() { return id; } } private static abstract class AbstractEngineResponse extends AbstractDbgMessage implements IDbgEngineResponse { protected int id; protected int status; @Override public int getID() { return this.id; } @Override public int getStatus() { return status; } @Override public void deserialize(DataInputStream in) throws IOException { id = in.readInt(); status = in.readInt(); } } private ZendDbgEngineMessages() { } // Engine notifications public static class DebuggerErrorNotification extends AbstractDbgMessage implements IDbgEngineNotification { private int errorLevel = 0; private String errorText; @Override public int getType() { return NOTIFICATION_DEBUGGER_ERROR; } @Override public void deserialize(DataInputStream in) throws IOException { errorLevel = in.readInt(); errorText = ZendDbgConnectionUtils.readString(in); } public int getErrorLevel() { return errorLevel; } public String getErrorText() { return errorText; } } public static class ScriptEndedNotification extends AbstractDbgMessage implements IDbgEngineNotification { private int status; @Override public int getType() { return NOTIFICATION_SRIPT_ENDED; } @Override public void deserialize(DataInputStream in) throws IOException { status = in.readInt(); } public int getStatus() { return status; } } public static class SessionStartedNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String fileName = ""; private String uri = ""; private String query = ""; private String additionalOptions = ""; private int protocolID; @Override public int getType() { return NOTIFICATION_SESSION_STARTED; } @Override public void deserialize(DataInputStream in) throws IOException { protocolID = in.readInt(); fileName = ZendDbgConnectionUtils.readString(in); uri = ZendDbgConnectionUtils.readString(in); query = URLDecoder.decode(ZendDbgConnectionUtils.readString(in), "UTF-8"); additionalOptions = ZendDbgConnectionUtils.readString(in); } public String getFileName() { return fileName; } public String getUri() { return uri; } public String getQuery() { return query; } public String getOptions() { return additionalOptions; } public int getServerProtocolID() { return protocolID; } } public static class HeaderOutputNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String output; @Override public int getType() { return NOTIFICATION_HEADER_OUTPUT; } @Override public void deserialize(DataInputStream in) throws IOException { output = ZendDbgConnectionUtils.readString(in); } public String getOutput() { return this.output; } } public static class IniAlteredNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String name; private String oldValue; private String newValue; @Override public int getType() { return NOTIFICATION_INI_ALTERED; } @Override public void deserialize(DataInputStream in) throws IOException { name = ZendDbgConnectionUtils.readString(in); oldValue = ZendDbgConnectionUtils.readString(in); newValue = ZendDbgConnectionUtils.readString(in); } public String getName() { return name; } public String getOldValue() { return oldValue; } public String getNewValue() { return newValue; } } public static class OutputNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String output = null; @Override public int getType() { return NOTIFICATION_OUTPUT; } @Override public void deserialize(DataInputStream in) throws IOException { output = ZendDbgConnectionUtils.readEncodedString(in, getTransferEncoding()); } public String getOutput() { return output; } } public static class ParsingErrorNotification extends AbstractDbgMessage implements IDbgEngineNotification { private int errorLevel = 0; private String fileName; private int lineNumber; private String errorText; @Override public int getType() { return NOTIFICATION_PARSING_ERROR; } @Override public void deserialize(DataInputStream in) throws IOException { errorLevel = in.readInt(); fileName = ZendDbgConnectionUtils.readString(in); lineNumber = in.readInt(); errorText = ZendDbgConnectionUtils.readString(in); } public int getErrorLevel() { return this.errorLevel; } public String getErrorText() { return this.errorText; } public String getFileName() { return this.fileName; } public int getLineNumber() { return this.lineNumber; } } public static class ReadyNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String fileName; private int lineNumber; @Override public int getType() { return NOTIFICATION_READY; } @Override public void deserialize(DataInputStream in) throws IOException { fileName = ZendDbgConnectionUtils.readString(in); lineNumber = in.readInt(); in.readInt(); // Read the 4 bytes of the watched-list length. this // is 0 now. } public String getFileName() { return fileName; } public int getLineNumber() { return lineNumber; } } public static class StartProcessFileNotification extends AbstractDbgMessage implements IDbgEngineNotification { private String fileName; @Override public int getType() { return NOTIFICATION_START_PROCESS_FILE; } @Override public void deserialize(DataInputStream in) throws IOException { fileName = ZendDbgConnectionUtils.readString(in); } public String getFileName() { return fileName; } } // Phantom message used to notify that connection was closed public static class CloseMessageHandlerNotification extends AbstractDbgMessage implements IDbgEngineNotification { @Override public void deserialize(DataInputStream in) throws IOException { // dummy } @Override public int getType() { return NOTIFICATION_CLOSE_MESSAGE_HANDLER; } } // Engine responses public static class AddBreakpointResponse extends AbstractEngineResponse { private int breakPointID; public int getBreakpointID() { return breakPointID; } @Override public int getType() { return RESPONSE_ADD_BREAKPOINT; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); breakPointID = in.readInt(); } } public static class AddFilesResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_ADD_FILES; } } public static class AssignValueResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_ASSIGN_VALUE; } } public static class DeleteAllBreakpointsResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_DELETE_ALL_BREAKPOINTS; } } public static class DeleteBreakpointResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_DELETE_BREAKPOINT; } } public static class EvalResponse extends AbstractEngineResponse { private String result; @Override public int getType() { return RESPONSE_EVAL; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); result = ZendDbgConnectionUtils.readString(in); } public String getResult() { return result; } } public static class GetCallStackResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_GET_CALL_STACK; } @Override public void deserialize(DataInputStream in) throws IOException { id = in.readInt(); // Just read data for now and do nothing with it... int depth = in.readInt(); for (int i = 0; i < depth; i++) { ZendDbgConnectionUtils.readString(in); in.readInt(); ZendDbgConnectionUtils.readString(in); ZendDbgConnectionUtils.readString(in); in.readInt(); ZendDbgConnectionUtils.readString(in); int params = in.readInt(); for (int j = 0; j < params; j++) { ZendDbgConnectionUtils.readEncodedString(in, getTransferEncoding()); ZendDbgConnectionUtils.readStringAsBytes(in); } } } } public static class GetCWDResponse extends AbstractEngineResponse { private String cwd; @Override public int getType() { return RESPONSE_GET_CWD; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); cwd = ZendDbgConnectionUtils.readString(in); } public String getCWD() { return cwd; } } public static class GetStackVariableValueResponse extends AbstractEngineResponse { private byte[] varResult; @Override public int getType() { return RESPONSE_GET_STACK_VARIABLE_VALUE; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); varResult = ZendDbgConnectionUtils.readStringAsBytes(in); } public byte[] getVarResult() { return varResult; } } public static class GetVariableValueResponse extends AbstractEngineResponse { private byte[] variableValue = null; @Override public int getType() { return RESPONSE_GET_VARIABLE_VALUE; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); variableValue = ZendDbgConnectionUtils.readStringAsBytes(in); } public byte[] getVariableValue() { return variableValue; } } public static class GoResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_GO; } } public static class PauseDebuggerResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_PAUSE_DEBUGGER; } } public static class SetProtocolResponse extends AbstractEngineResponse { private int protocolID; @Override public int getType() { return RESPONSE_SET_PROTOCOL; } @Override public void deserialize(DataInputStream in) throws IOException { id = in.readInt(); protocolID = in.readInt(); } public int getProtocolID() { return protocolID; } } public static class StartResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_START; } } public static class StepIntoResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_STEP_INTO; } } public static class StepOutResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_STEP_OUT; } } public static class StepOverResponse extends AbstractEngineResponse { @Override public int getType() { return RESPONSE_STEP_OVER; } } public static class UnknownMessageResponse extends AbstractEngineResponse { private int origint; @Override public int getType() { return RESPONSE_UNKNOWN; } @Override public void deserialize(DataInputStream in) throws IOException { id = in.readInt(); origint = in.readInt(); } public int getOriginalInt() { return origint; } } // Engine requests public static class GetLocalFileContentRequest extends AbstractEngineRequest<GetLocalFileContentResponse> { private String fileName; private int size; private int checkSum; @Override public int getType() { return REQUEST_GET_LOCAL_FILE_CONTENT; } @Override public void deserialize(DataInputStream in) throws IOException { super.deserialize(in); fileName = ZendDbgConnectionUtils.readString(in); size = in.readInt(); checkSum = in.readInt(); } public String getFileName() { return fileName; } public int getSize() { return size; } public int getCheckSum() { return checkSum; } } public static IDbgEngineMessage create(int type) { switch (type) { // Engine notifications case NOTIFICATION_DEBUGGER_ERROR: return new DebuggerErrorNotification(); case NOTIFICATION_HEADER_OUTPUT: return new HeaderOutputNotification(); case NOTIFICATION_INI_ALTERED: return new IniAlteredNotification(); case NOTIFICATION_OUTPUT: return new OutputNotification(); case NOTIFICATION_PARSING_ERROR: return new ParsingErrorNotification(); case NOTIFICATION_READY: return new ReadyNotification(); case NOTIFICATION_SESSION_STARTED: return new SessionStartedNotification(); case NOTIFICATION_SRIPT_ENDED: return new ScriptEndedNotification(); case NOTIFICATION_START_PROCESS_FILE: return new StartProcessFileNotification(); // Engine responses case RESPONSE_ADD_BREAKPOINT: return new AddBreakpointResponse(); case RESPONSE_ADD_FILES: return new AddFilesResponse(); case RESPONSE_ASSIGN_VALUE: return new AssignValueResponse(); case RESPONSE_DELETE_ALL_BREAKPOINTS: return new DeleteAllBreakpointsResponse(); case RESPONSE_DELETE_BREAKPOINT: return new DeleteBreakpointResponse(); case RESPONSE_EVAL: return new EvalResponse(); case RESPONSE_GET_CALL_STACK: return new GetCallStackResponse(); case RESPONSE_GET_CWD: return new GetCWDResponse(); case RESPONSE_GET_STACK_VARIABLE_VALUE: return new GetStackVariableValueResponse(); case RESPONSE_GET_VARIABLE_VALUE: return new GetVariableValueResponse(); case RESPONSE_GO: return new GoResponse(); case RESPONSE_PAUSE_DEBUGGER: return new PauseDebuggerResponse(); case RESPONSE_SET_PROTOCOL: return new SetProtocolResponse(); case RESPONSE_START: return new StartResponse(); case RESPONSE_STEP_INTO: return new StepIntoResponse(); case RESPONSE_STEP_OUT: return new StepOutResponse(); case RESPONSE_STEP_OVER: return new StepOverResponse(); // Engine requests case REQUEST_GET_LOCAL_FILE_CONTENT: return new GetLocalFileContentRequest(); } return null; } }