Further work on machine launch configs
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / launch / MachineDebugTarget.java
1 package net.mograsim.plugin.launch;
2
3 import java.util.Arrays;
4
5 import org.eclipse.core.resources.IMarkerDelta;
6 import org.eclipse.core.runtime.IStatus;
7 import org.eclipse.core.runtime.PlatformObject;
8 import org.eclipse.core.runtime.Status;
9 import org.eclipse.debug.core.DebugEvent;
10 import org.eclipse.debug.core.DebugException;
11 import org.eclipse.debug.core.DebugPlugin;
12 import org.eclipse.debug.core.ILaunch;
13 import org.eclipse.debug.core.ILaunchConfiguration;
14 import org.eclipse.debug.core.model.IBreakpoint;
15 import org.eclipse.debug.core.model.IDebugElement;
16 import org.eclipse.debug.core.model.IDebugTarget;
17 import org.eclipse.debug.core.model.IMemoryBlock;
18 import org.eclipse.debug.core.model.IProcess;
19 import org.eclipse.debug.core.model.IStepFilters;
20 import org.eclipse.debug.core.model.IThread;
21
22 import net.mograsim.machine.Machine;
23 import net.mograsim.plugin.MograsimActivator;
24
25 public class MachineDebugTarget extends PlatformObject implements IDebugTarget
26 {
27         private final MachineProcess process;
28
29         public MachineDebugTarget(MachineProcess process)
30         {
31                 this.process = process;
32
33                 DebugPlugin.getDefault().addDebugEventListener(es -> Arrays.stream(es).filter(e -> e.getSource() == process).forEach(e ->
34                 {
35                         switch (e.getKind())
36                         {
37                         case DebugEvent.RESUME:
38                                 fireResumeEvent(e.getDetail());
39                                 break;
40                         case DebugEvent.SUSPEND:
41                                 fireSuspendEvent(e.getDetail());
42                                 break;
43                         case DebugEvent.TERMINATE:
44                                 fireTerminateEvent();
45                                 break;
46                         default:
47                                 // ignore
48                         }
49                 }));
50
51                 getLaunch().addDebugTarget(this);
52                 fireCreationEvent();
53         }
54
55         public Machine getMachine()
56         {
57                 return process.getMachine();
58         }
59
60         @Override
61         public String getName() throws DebugException
62         {
63                 return process.getName();
64         }
65
66         @Override
67         public String getModelIdentifier()
68         {
69                 return MograsimActivator.PLUGIN_ID;
70         }
71
72         @Override
73         public IDebugTarget getDebugTarget()
74         {
75                 return this;
76         }
77
78         @Override
79         public ILaunch getLaunch()
80         {
81                 return process.getLaunch();
82         }
83
84         public void setExecutionSpeed(double speed)
85         {
86                 process.setExecutionSpeed(speed);
87         }
88
89         @Override
90         public boolean isSuspended()
91         {
92                 return process.isSuspended();
93         }
94
95         @Override
96         public boolean canSuspend()
97         {
98                 return process.canSuspend();
99         }
100
101         @Override
102         public void suspend() throws DebugException
103         {
104                 process.suspend();
105         }
106
107         @Override
108         public boolean canResume()
109         {
110                 return process.canResume();
111         }
112
113         @Override
114         public void resume() throws DebugException
115         {
116                 process.resume();
117         }
118
119         @Override
120         public boolean isTerminated()
121         {
122                 return process.isTerminated();
123         }
124
125         @Override
126         public boolean canTerminate()
127         {
128                 return process.canTerminate();
129         }
130
131         @Override
132         public void terminate() throws DebugException
133         {
134                 process.terminate();
135         }
136
137         @Override
138         public boolean supportsBreakpoint(IBreakpoint breakpoint)
139         {
140                 return false;
141         }
142
143         @Override
144         public void breakpointAdded(IBreakpoint breakpoint)
145         {
146                 // ignore; we don't support breakpoints
147         }
148
149         @Override
150         public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta)
151         {
152                 // ignore; we don't support breakpoints
153         }
154
155         @Override
156         public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta)
157         {
158                 // ignore; we don't support breakpoints
159         }
160
161         @Override
162         public boolean isDisconnected()
163         {
164                 return false;
165         }
166
167         @Override
168         public boolean canDisconnect()
169         {
170                 return false;
171         }
172
173         @Override
174         public void disconnect() throws DebugException
175         {
176                 throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.NOT_SUPPORTED,
177                                 "Can't disconnect from a MachineDebugTarget", null));
178         }
179
180         @Override
181         public boolean supportsStorageRetrieval()
182         {
183                 return true;
184         }
185
186         @Override
187         public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException
188         {
189                 return new MainMemoryBlock(this, startAddress, length);
190         }
191
192         @Override
193         public MachineProcess getProcess()
194         {
195                 return process;
196         }
197
198         @Override
199         public boolean hasThreads() throws DebugException
200         {
201                 return false;
202         }
203
204         @Override
205         public IThread[] getThreads() throws DebugException
206         {
207                 return new IThread[0];
208         }
209
210         @SuppressWarnings("unchecked")
211         @Override
212         public <T> T getAdapter(Class<T> adapter)
213         {
214                 if (adapter == IDebugElement.class)
215                         return (T) this;
216
217                 // leave this here; maybe we implement IStepFilters someday
218                 if (adapter == IStepFilters.class)
219                         if (this instanceof IStepFilters)
220                                 return (T) getDebugTarget();
221
222                 if (adapter == IDebugTarget.class)
223                         return (T) getDebugTarget();
224
225                 if (adapter == ILaunch.class)
226                         return (T) getLaunch();
227
228                 if (adapter == IProcess.class)
229                         return (T) getProcess();
230
231                 // CONTEXTLAUNCHING
232                 if (adapter == ILaunchConfiguration.class)
233                         return (T) getLaunch().getLaunchConfiguration();
234
235                 return super.getAdapter(adapter);
236         }
237
238         /**
239          * Fires a creation event for this debug element.
240          */
241         private void fireCreationEvent()
242         {
243                 fireEvent(new DebugEvent(this, DebugEvent.CREATE));
244         }
245
246         /**
247          * Fires a resume for this debug element with the specified detail code.
248          *
249          * @param detail detail code for the resume event, such as <code>DebugEvent.STEP_OVER</code>
250          */
251         private void fireResumeEvent(int detail)
252         {
253                 fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
254         }
255
256         /**
257          * Fires a suspend event for this debug element with the specified detail code.
258          *
259          * @param detail detail code for the suspend event, such as <code>DebugEvent.BREAKPOINT</code>
260          */
261         private void fireSuspendEvent(int detail)
262         {
263                 fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
264         }
265
266         /**
267          * Fires a terminate event for this debug element.
268          */
269         private void fireTerminateEvent()
270         {
271                 fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
272         }
273
274         /**
275          * Fires a debug event.
276          *
277          * @param event debug event to fire
278          */
279         private static void fireEvent(DebugEvent event)
280         {
281                 DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { event });
282         }
283 }