/******************************************************************************* * Copyright (c) 2005 - 2007 committers of openArchitectureWare 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: * committers of openArchitectureWare - initial API and implementation *******************************************************************************/ package org.eclipse.emf.mwe.internal.core.debug.processing.handlers; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.emf.mwe.core.debug.model.SyntaxElement; import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter; import org.eclipse.emf.mwe.internal.core.debug.communication.Connection; import org.eclipse.emf.mwe.internal.core.debug.communication.packages.BreakpointPackage; import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor; import org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler; import org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler; /** * This class handles the communication of Breakpoints on the runtime side. It * listens in an extra thread for set and removal of breakpoints. The * <code>DebugMonitor</code> uses this class to suspend the runtime process at * breakpoints. */ public class BreakpointRuntimeHandler implements RuntimeHandler, ProcessHandler, Runnable { public static final int SET = 1; public static final int REMOVE = 2; protected Connection connection; protected DebugMonitor monitor; private final List<Object> breakpoints = new ArrayList<Object>(); private final List<SyntaxElement> breakpointTOs = new ArrayList<SyntaxElement>(); private final List<SyntaxElement> toBeRemovedTOs = new ArrayList<SyntaxElement>(); // ------------------------------------------------------------------------- /** * @see org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler#init(org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor, * org.eclipse.emf.mwe.internal.core.debug.communication.Connection) */ public void init(final DebugMonitor monitor, final Connection connection) { this.monitor = monitor; this.connection = connection; if (monitor != null) { monitor.addProcessHandler(this); } } /** * @see org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler#startListener() */ public void startListener() { Thread thread = new Thread(this, getClass().getSimpleName()); thread.setDaemon(true); thread.start(); } /** * @see java.lang.Runnable#run() */ public void run() { try { while (true) { listenAndDispatchCommand(); } } catch (IOException e) { } } private void listenAndDispatchCommand() throws IOException { handle((BreakpointPackage) connection.listenForPackage(BreakpointPackage.class)); } private void handle(final BreakpointPackage packet) { switch (packet.type) { case SET: doSet(packet.se, null, 0); break; case REMOVE: doRemove(packet.se, null, 0); break; default: break; } } // ------------------------------------------------------------------------- private void doSet(final SyntaxElement se, final Object actual, final int flag) { ElementAdapter adapter = monitor.getAdapter(se); if (adapter == null) return; Object element = adapter.findElement(se, actual, flag); // breakpoints may be set before the syntax element structure is // instantiated // in this case we store the SyntaxElement and try it again during // shallSuspend(...) if (element == null) { breakpointTOs.add(se); for (SyntaxElement cand : toBeRemovedTOs) { if (se.equalsBP(cand)) { toBeRemovedTOs.remove(cand); break; } } } else { breakpoints.add(element); } } private void doRemove(final SyntaxElement se, final Object actual, final int flag) { ElementAdapter adapter = monitor.getAdapter(se); if (adapter == null) return; Object element = adapter.findElement(se, actual, flag); if (element == null) { toBeRemovedTOs.add(se); for (SyntaxElement cand : breakpointTOs) { if (se.equalsBP(cand)) { breakpointTOs.remove(cand); break; } } } else { breakpoints.remove(element); } } // ------------------------------------------------------------------------- // process listener implementation public boolean isLastCall() { return false; } /** * returns true if a breakpoint is rgeistered for that element * * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallSuspend(boolean, * java.lang.Object, int) */ public boolean shallSuspend(final boolean lastState, final Object element, final int flag) { if (!toBeRemovedTOs.isEmpty()) { List<SyntaxElement> temp = new ArrayList<SyntaxElement>(); temp.addAll(toBeRemovedTOs); toBeRemovedTOs.clear(); for (SyntaxElement se : temp) { doRemove(se, element, flag); } } if (!breakpointTOs.isEmpty()) { List<SyntaxElement> temp = new ArrayList<SyntaxElement>(); temp.addAll(breakpointTOs); breakpointTOs.clear(); for (SyntaxElement se : temp) { doSet(se, element, flag); } } return lastState || breakpoints.contains(element); } /** * no contribution here * * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallHandle(boolean, * java.lang.Object, int) */ public boolean shallHandle(final boolean lastState, final Object element, final int flag) { return lastState; } /** * no contribution here * * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallInterrupt(boolean) */ public boolean shallInterrupt(final boolean lastState) { return lastState; } }