| /*=============================================================================# |
| # Copyright (c) 2008, 2017 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.rj.server; |
| |
| import java.io.Externalizable; |
| import java.io.IOException; |
| import java.io.ObjectInput; |
| import java.io.ObjectOutput; |
| |
| import org.eclipse.statet.rj.data.RJIO; |
| import org.eclipse.statet.rj.data.RJIOExternalizable; |
| import org.eclipse.statet.rj.server.dbg.CallStack; |
| import org.eclipse.statet.rj.server.dbg.CtrlReport; |
| import org.eclipse.statet.rj.server.dbg.DbgEnablement; |
| import org.eclipse.statet.rj.server.dbg.DbgFilterState; |
| import org.eclipse.statet.rj.server.dbg.DbgRequest; |
| import org.eclipse.statet.rj.server.dbg.ElementTracepointInstallationRequest; |
| import org.eclipse.statet.rj.server.dbg.FlagTracepointInstallationRequest; |
| import org.eclipse.statet.rj.server.dbg.FrameContext; |
| import org.eclipse.statet.rj.server.dbg.FrameContextDetailRequest; |
| import org.eclipse.statet.rj.server.dbg.SetDebugReport; |
| import org.eclipse.statet.rj.server.dbg.SetDebugRequest; |
| import org.eclipse.statet.rj.server.dbg.TracepointEvent; |
| import org.eclipse.statet.rj.server.dbg.TracepointInstallationReport; |
| import org.eclipse.statet.rj.server.dbg.TracepointStatesUpdate; |
| |
| |
| /** |
| * Command item for main loop dbg operations (="op") |
| */ |
| public final class DbgCmdItem extends MainCmdItem implements RjsComObject, Externalizable { |
| |
| // -- C2S sync |
| public static final byte OP_LOAD_FRAME_LIST= 0001; |
| public static final byte OP_LOAD_FRAME_CONTEXT= 0002; |
| public static final byte OP_SET_DEBUG= 0003; |
| public static final byte OP_REQUEST_SUSPEND= 0004; |
| // public static final byte OP_CTRL_SUSPEND= 0010; |
| public static final byte OP_CTRL_RESUME= 0011; |
| public static final byte OP_CTRL_STEP_INTO= 0012; |
| public static final byte OP_CTRL_STEP_OVER= 0014; |
| public static final byte OP_CTRL_STEP_RETURN= 0016; |
| public static final byte OP_INSTALL_TP_FLAGS= 0020; |
| public static final byte OP_INSTALL_TP_POSITIONS= 0021; |
| |
| // -- C2S sync + async |
| public static final byte OP_SET_ENABLEMENT= 0031; |
| public static final byte OP_RESET_FILTER_STATE= 0032; |
| public static final byte OP_UPDATE_TP_STATES= 0034; |
| |
| public static final byte OP_C2S_S2C= 0040; |
| |
| public static final byte OP_NOTIFY_TP_EVENT= 0x41; |
| |
| |
| private static final int OV_WITHDATA= 0x01000000; |
| private static final int OV_WITHSTATUS= 0x08000000; |
| |
| |
| public static interface CustomDataReader { |
| |
| Object read(byte type, boolean answer, RJIO io) throws IOException; |
| |
| } |
| |
| private static Object readData(final RJIO io, final byte type, final boolean answer) throws IOException { |
| if (!answer) { |
| switch (type) { |
| case OP_LOAD_FRAME_LIST: |
| return null; |
| case OP_LOAD_FRAME_CONTEXT: |
| return new FrameContextDetailRequest(io); |
| case OP_SET_DEBUG: |
| return new SetDebugRequest(io); |
| case OP_REQUEST_SUSPEND: |
| return null; |
| case OP_CTRL_RESUME: |
| return new DbgRequest.Resume(io); |
| case OP_CTRL_STEP_INTO: |
| return new DbgRequest.StepInto(io); |
| case OP_CTRL_STEP_OVER: |
| return new DbgRequest.StepOver(io); |
| case OP_CTRL_STEP_RETURN: |
| return new DbgRequest.StepReturn(io); |
| case OP_SET_ENABLEMENT: |
| return new DbgEnablement(io); |
| case OP_RESET_FILTER_STATE: |
| return new DbgFilterState(io); |
| case OP_INSTALL_TP_FLAGS: |
| return new FlagTracepointInstallationRequest(io); |
| case OP_INSTALL_TP_POSITIONS: |
| return new ElementTracepointInstallationRequest(io); |
| case OP_UPDATE_TP_STATES: |
| return new TracepointStatesUpdate(io); |
| case OP_NOTIFY_TP_EVENT: |
| return new TracepointEvent(io); |
| default: |
| break; |
| } |
| throw new IOException("Unsupported type= " + type); //$NON-NLS-1$ |
| } |
| else { |
| switch (type) { |
| case OP_LOAD_FRAME_LIST: |
| return new CallStack(io); |
| case OP_LOAD_FRAME_CONTEXT: |
| return new FrameContext(io); |
| case OP_SET_DEBUG: |
| return new SetDebugReport(io); |
| case OP_REQUEST_SUSPEND: |
| break; // status |
| case OP_CTRL_RESUME: |
| case OP_CTRL_STEP_INTO: |
| case OP_CTRL_STEP_OVER: |
| case OP_CTRL_STEP_RETURN: |
| return new CtrlReport(io); |
| case OP_SET_ENABLEMENT: |
| case OP_RESET_FILTER_STATE: |
| break; // status |
| case OP_INSTALL_TP_FLAGS: |
| case OP_INSTALL_TP_POSITIONS: |
| return new TracepointInstallationReport(io); |
| case OP_UPDATE_TP_STATES: |
| break; // status |
| default: |
| break; |
| } |
| throw new IOException("Unsupported type= " + type); //$NON-NLS-1$ |
| } |
| } |
| |
| |
| private byte op; |
| |
| private Object data; |
| |
| private RjsStatus status; |
| |
| |
| /** |
| * Constructor for new commands |
| */ |
| public DbgCmdItem(final byte op, final int options, |
| final RJIOExternalizable data) { |
| this.op= op; |
| this.options= (options & OM_CUSTOM); |
| if (data != null) { |
| this.options |= OV_WITHDATA; |
| } |
| if (op < OP_NOTIFY_TP_EVENT) { |
| this.options |= OV_WAITFORCLIENT; |
| } |
| this.data= data; |
| } |
| |
| /** |
| * Constructor for automatic deserialization |
| */ |
| public DbgCmdItem() { |
| } |
| |
| /** |
| * Constructor for deserialization |
| */ |
| public DbgCmdItem(final RJIO io) throws IOException { |
| readExternal(io, null); |
| } |
| |
| /** |
| * Constructor for deserialization |
| */ |
| public DbgCmdItem(final RJIO io, final CustomDataReader reader) throws IOException { |
| readExternal(io, reader); |
| } |
| |
| @Override |
| public void writeExternal(final RJIO io) throws IOException { |
| io.writeInt(this.options); |
| io.writeByte(this.op); |
| if ((this.options & OV_WITHSTATUS) != 0) { |
| this.status.writeExternal(io); |
| } |
| else if ((this.options & OV_WITHDATA) != 0) { |
| ((RJIOExternalizable) this.data).writeExternal(io); |
| } |
| } |
| |
| @Override |
| public void writeExternal(final ObjectOutput out) throws IOException { |
| final RJIO io= RJIO.get(out); |
| final int check= io.writeCheck1(); |
| writeExternal(io); |
| io.writeCheck2(check); |
| io.disconnect(out); |
| } |
| |
| private void readExternal(final RJIO io, final CustomDataReader reader) throws IOException { |
| this.options= io.readInt(); |
| this.op= io.readByte(); |
| if ((this.options & OV_WITHSTATUS) != 0) { |
| this.status= new RjsStatus(io); |
| } |
| else if ((this.options & OV_WITHDATA) != 0) { |
| final boolean answer= ((this.options & OV_ANSWER) != 0); |
| if (reader != null) { |
| this.data= reader.read(this.op, answer, io); |
| if (this.data == null) { |
| this.data= readData(io, this.op, answer); |
| } |
| } |
| else { |
| this.data= readData(io, this.op, answer); |
| } |
| } |
| } |
| |
| @Override |
| public void readExternal(final ObjectInput in) throws IOException { |
| final RJIO io= RJIO.get(in); |
| final int check= io.readCheck1(); |
| readExternal(io, null); |
| io.readCheck2(check); |
| io.disconnect(in); |
| } |
| |
| |
| @Override |
| public int getComType() { |
| return T_DBG; |
| } |
| |
| @Override |
| public byte getCmdType() { |
| return T_DBG_ITEM; |
| } |
| |
| |
| @Override |
| public void setAnswer(final RjsStatus status) { |
| assert (status != null); |
| if (status == RjsStatus.OK_STATUS) { |
| this.options= (this.options & OM_CLEARFORANSWER) | OV_ANSWER; |
| this.status= null; |
| this.data= null; |
| } |
| else { |
| this.options= (this.options & OM_CLEARFORANSWER) | (OV_ANSWER | OV_WITHSTATUS); |
| this.status= status; |
| this.data= null; |
| } |
| } |
| |
| public void setAnswer(final RJIOExternalizable data) { |
| this.options= (this.options & OM_CLEARFORANSWER) | OV_ANSWER; |
| if (data != null) { |
| this.options |= OV_WITHDATA; |
| } |
| this.status= null; |
| this.data= data; |
| } |
| |
| |
| @Override |
| public byte getOp() { |
| return this.op; |
| } |
| |
| @Override |
| public boolean isOK() { |
| return (this.status == null || this.status.getSeverity() == RjsStatus.OK); |
| } |
| |
| @Override |
| public RjsStatus getStatus() { |
| return this.status; |
| } |
| |
| @Override |
| public String getDataText() { |
| return null; |
| } |
| |
| public Object getData() { |
| return this.data; |
| } |
| |
| |
| @Override |
| public boolean testEquals(final MainCmdItem other) { |
| if (!(other instanceof DbgCmdItem)) { |
| return false; |
| } |
| final DbgCmdItem otherItem= (DbgCmdItem) other; |
| if (getOp() != otherItem.getOp()) { |
| return false; |
| } |
| if (this.options != otherItem.options) { |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| final StringBuffer sb= new StringBuffer(100); |
| sb.append("DbgCmdItem "); //$NON-NLS-1$ |
| switch (this.op) { |
| case OP_LOAD_FRAME_LIST: |
| sb.append("LOAD_FRAME_LIST"); //$NON-NLS-1$ |
| break; |
| case OP_LOAD_FRAME_CONTEXT: |
| sb.append("LOAD_FRAME_CONTEXT"); //$NON-NLS-1$ |
| break; |
| case OP_SET_DEBUG: |
| sb.append("SET_DEBUG"); //$NON-NLS-1$ |
| break; |
| case OP_REQUEST_SUSPEND: |
| sb.append("REQUEST_SUSPEND"); //$NON-NLS-1$ |
| break; |
| case OP_CTRL_RESUME: |
| sb.append("CTRL_RESUME"); //$NON-NLS-1$ |
| break; |
| case OP_CTRL_STEP_INTO: |
| sb.append("CTRL_STEP_INTO"); //$NON-NLS-1$ |
| break; |
| case OP_CTRL_STEP_OVER: |
| sb.append("CTRL_STEP_OVER"); //$NON-NLS-1$ |
| break; |
| case OP_CTRL_STEP_RETURN: |
| sb.append("CTRL_STEP_RETURN"); //$NON-NLS-1$ |
| break; |
| case OP_INSTALL_TP_FLAGS: |
| sb.append("INSTALL_TP_FLAGS"); //$NON-NLS-1$ |
| break; |
| case OP_INSTALL_TP_POSITIONS: |
| sb.append("INSTALL_TP_POSITIONS"); //$NON-NLS-1$ |
| break; |
| case OP_SET_ENABLEMENT: |
| sb.append("SET_ENABLEMENT"); //$NON-NLS-1$ |
| break; |
| case OP_RESET_FILTER_STATE: |
| sb.append("RESET_FILTER_STATE"); //$NON-NLS-1$ |
| break; |
| case OP_UPDATE_TP_STATES: |
| sb.append("UPDATE_TRACEPOINTS_STATES"); //$NON-NLS-1$ |
| break; |
| case OP_NOTIFY_TP_EVENT: |
| sb.append("NOTIFY_TP_EVENT"); //$NON-NLS-1$ |
| break; |
| default: |
| sb.append(this.op); |
| break; |
| } |
| sb.append("\n\t" + "options= 0x").append(Integer.toHexString(this.options)); //$NON-NLS-1$ //$NON-NLS-2$ |
| if ((this.options & OV_WITHDATA) != 0) { |
| sb.append("\n<DATA>\n"); //$NON-NLS-1$ |
| sb.append(this.data); |
| sb.append("\n</DATA>"); //$NON-NLS-1$ |
| } |
| return sb.toString(); |
| } |
| |
| } |