/** * */ package org.dresdenocl.debug.model; import static org.dresdenocl.debug.model.EOclDebugMessageType.ADD_LINE_BREAKPOINT; import static org.dresdenocl.debug.model.EOclDebugMessageType.EXIT; import static org.dresdenocl.debug.model.EOclDebugMessageType.GET_STACK; import static org.dresdenocl.debug.model.EOclDebugMessageType.REMOVE_LINE_BREAKPOINT; import static org.dresdenocl.debug.model.EOclDebugMessageType.RESUME; import static org.dresdenocl.debug.model.EOclDebugMessageType.STEP_INTO; import static org.dresdenocl.debug.model.EOclDebugMessageType.STEP_OVER; import static org.dresdenocl.debug.model.EOclDebugMessageType.STEP_RETURN; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.dresdenocl.debug.IOclDebuggable; import org.dresdenocl.debug.util.OclPair; import org.dresdenocl.debug.util.OclStringUtil; /** * @author Lars Schuetze * */ public class OclDebuggerListener implements Runnable { private OclDebugCommunicationHelper m_communicationHelper; private Map<Long, OclPair<String, Object>> m_objectMap; private int m_requestPort; private IOclDebuggable m_debuggable; private boolean m_stop; private long m_id; public OclDebuggerListener(int requestPort) { m_requestPort = requestPort; m_communicationHelper = new OclDebugCommunicationHelper(); m_objectMap = new LinkedHashMap<Long, OclPair<String, Object>>(); m_stop = false; m_id = 0; } public IOclDebuggable getDebuggable() { return m_debuggable; } public void setDebuggable(IOclDebuggable debuggable) { m_debuggable = debuggable; } @Override public void run() { try { runDebugger(); } catch (IOException e) { e.printStackTrace(); } } private void runDebugger() throws IOException { ServerSocket server = new ServerSocket(m_requestPort); Socket accept = server.accept(); InputStream inputStream = accept.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); PrintStream output = new PrintStream(accept.getOutputStream()); OclDebugMessage command; while (!m_stop) { System.out.println("OclDebuggerListener m_stop = " + m_stop); command = m_communicationHelper.receive(reader); System.out.println("OclDebuggerListener command = " + command); if (command == null) { break; } if (command.hasType(EXIT)) { m_debuggable.terminate(); m_stop = true; } else if (command.hasType(RESUME)) { System.out.println("OclDebuggerListener RESUME"); m_debuggable.resume(); } else if (command.hasType(STEP_OVER)) { m_debuggable.stepOver(); } else if (command.hasType(STEP_INTO)) { m_debuggable.stepInto(); } else if (command.hasType(STEP_RETURN)) { m_debuggable.stepReturn(); } else if (command.hasType(ADD_LINE_BREAKPOINT)) { String location = command.getArgument(0); int line = Integer.parseInt(command.getArgument(1)); m_debuggable.addLineBreakPoint(location, line); } else if (command.hasType(REMOVE_LINE_BREAKPOINT)) { String location = command.getArgument(0); int line = Integer.parseInt(command.getArgument(1)); m_debuggable.removeLineBreakPoint(location, line); } else if (command.hasType(GET_STACK)) { final String[] stack = m_debuggable.getStack(); String controlStack = OclStringUtil.encode('#', stack); OclDebugMessage message = new OclDebugMessage(EOclDebugMessageType.GET_STACK_RESPONSE, new String[] { controlStack }); m_communicationHelper.sendEvent(message, output); } else if (command.hasType(EOclDebugMessageType.GET_FRAME_VARIABLES)) { String stackFrame = command.getArgument(0); Map<String, Object> frameVariables = m_debuggable.getFrameVariables(stackFrame); List<String> variableIds = new LinkedList<String>(); for (String name : frameVariables.keySet()) { Object value = frameVariables.get(name); long id = getObjectId(name, value); variableIds.add(Long.toString(id)); } OclDebugMessage message = new OclDebugMessage( EOclDebugMessageType.GET_FRAME_VARIABLES_RESPONSE, variableIds.toArray(new String[0])); m_communicationHelper.sendEvent(message, output); } else if (command.hasType(EOclDebugMessageType.GET_VARIABLES)) { String[] arguments = command.getArguments(); List<String> varStrings = new LinkedList<String>(); for (String argument : arguments) { Long id = Long.parseLong(argument); Object next = m_objectMap.get(id).getRight(); String varString = convertToString(id, next); varStrings.add(varString); } OclDebugMessage message = new OclDebugMessage(EOclDebugMessageType.GET_VARIABLES_RESPONSE, varStrings.toArray(new String[0])); m_communicationHelper.sendEvent(message, output); } else if (command.hasType(EOclDebugMessageType.CONSTRAINT_INTERPRETED)) { // ignore this event } else { System.out.println("ERROR: Unrecognized command (" + command + ")!"); output.append("Unrecognized command!"); } } System.out.println("OclDebuggerListener END WHILE"); //m_objectMap.clear(); server.close(); } private String convertToString(long id, Object object) { String name = m_objectMap.get(id).getLeft(); Map<String, Object> properties = new LinkedHashMap<String, Object>(); properties.put("!name", name); properties.put("!id", Long.toString(id)); properties.put("!type", object.getClass().toString()); properties.put("!valueString", object.toString()); return OclStringUtil.convertToString(properties); } private long getObjectId(String name, Object value) { OclPair<String, Object> pair = new OclPair<String, Object>(name, value); if (m_objectMap.containsValue(pair)) { for (Long nextId : m_objectMap.keySet()) { OclPair<String, Object> p = m_objectMap.get(nextId); if (pair.equals(p)) { return nextId; } } } else { long id = m_id++; m_objectMap.put(id, pair); return id; } return -1; } }