src/main/java/xelfi/debugger/Debugger.java
author Jaroslav Tulach <jaroslav.tulach@xelfi.cz>
Tue, 17 Jan 2017 21:12:37 +0100
branchDirtyFix
changeset 10 fe294d0f1297
parent 0 189280700bc7
permissions -rw-r--r--
Making the project compilable
     1 /**
     2  * Debugger
     3  *
     4  * @author Roman Blazevic
     5  * @version 970326
     6  */
     7 
     8 package xelfi.debugger;
     9 
    10 import java.io.IOException;
    11 import java.util.*;
    12 import java.awt.Color;
    13 import java.awt.Panel;
    14 import xelfi.util.EnhProperties;
    15 import xelfi.top.*;
    16 import xelfi.editor.*;
    17 import xelfi.xedit.JavaEditorFrame;
    18 import xelfi.compiler.Output;
    19 import xelfi.execution.RunOptions;
    20 
    21 //import symantec.tools.debug.*; // doesn't need TCP/IP
    22 
    23 /**
    24  * This is a main class of the Xelfi debugger.
    25  * It is also a document on which several views can exist
    26  * (LocalsView, CallStackView and ThreadsView).
    27  */
    28 
    29 public class Debugger implements DebuggerCallback, BackgroundCallback, XFColorCallback, XelfiOptions
    30 {
    31 	private DebuggerOptions options;
    32 
    33 	private Vector remoteDebuggers;
    34 
    35 	private boolean debuggingSession; // just debugging
    36 
    37 	private RemoteDebugger remoteDebugger;
    38 	private RemoteThreadGroup currentThreadGroup;
    39 	private RemoteThread currentThread;
    40 
    41 	private Watches watches;
    42 	private Breakpoints breakpoints;
    43 
    44 	private LocalsView localsView;
    45 	private CallStackView callStackView;
    46 	private ThreadsView threadsView;
    47 
    48 	private Position currentPosition = null; //some position on the current line
    49 
    50 	private Breakpoint temporaryBreakpoint = null; //used "while going to cursor"
    51 
    52 	// bude se delat trochu jinak
    53 	private Color currentLineBackgroundColor;
    54 	private Color breakpointLineBackgroundColor;
    55 	private Color currentLineForegroundColor;
    56 	private Color breakpointLineForegroundColor;
    57 	private Color foregroundColor; // filled in getBackground()
    58 
    59 	private boolean canEnableGoFlag = true;
    60 	private boolean canEnableGoToCursorFlag = true;
    61 
    62 	/**
    63 	 * Debugger constructor.
    64 	 */
    65 	public Debugger()
    66 	{
    67 		options = new DebuggerOptions();
    68 
    69 		remoteDebuggers = new Vector();
    70 
    71 		watches = new Watches(this);
    72 		breakpoints = new Breakpoints(this);
    73 
    74 		localsView = new LocalsView(this);
    75 		callStackView = new CallStackView(this);
    76 		threadsView = new ThreadsView(this);
    77 		remoteDebugger = null;
    78 		currentThreadGroup = null;
    79 		currentThread = null;
    80 		debuggingSession = false;
    81 
    82 		XFColor.addCallback(this);
    83 		TopLevel.addOption(this);
    84 	}
    85 
    86 	/**
    87 	 * Implementation of the breakpointEvent from the DebuggerCallback
    88 	 */
    89 	public void breakpointEvent(RemoteThread t) throws Exception
    90 	{
    91 		canEnableGoFlag = true;
    92 		canEnableGoToCursorFlag = true;
    93 
    94 		TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
    95 		TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);
    96 		TopLevel.getMenu().enableItem(MainMenu.miDebugTraceOver);
    97 		TopLevel.getMenu().enableItem(MainMenu.miDebugTraceInto);
    98 
    99 		RemoteStackFrame[] stack = t.dumpStack();
   100 
   101 		if (stack.length > 0)
   102 		{
   103 			//TopLevel.getOutput().println(stack[0].toString());
   104 			currentThread = t;
   105 		}
   106 		else
   107 		{
   108 			TopLevel.getOutput().show();
   109 			TopLevel.getOutput().println("invalid thread specified in breakpoint");
   110 		}
   111 
   112 		if (getCurrentStackFrameIndex() == stack.length-1)
   113 		{
   114 			internalFinishDebugging(); // nebo vyber dalsi thread, ktery je na breakpointu;
   115 			return;
   116 		}
   117 
   118 		String className = new String();
   119 
   120 		try
   121 		{
   122 			// try to find out the class name and the line number on which we has stopped
   123 			StringTokenizer st = new StringTokenizer(stack[0].toString(), ".()");
   124 			int lineNumber = -1;
   125 			int nTokens = st.countTokens();
   126 
   127 			for(int i = 3; i < nTokens; i++) // n-3 times
   128 				className = className+st.nextToken()+".";
   129 
   130 			className += st.nextToken();
   131 
   132 			st.nextToken();
   133 			st.nextToken(":");
   134 			lineNumber = Integer.valueOf(st.nextToken(":)")).intValue();
   135 
   136 			// decide if we have stopped on the temporary breakpoint
   137 			if (temporaryBreakpoint != null)
   138 				if (lineNumber == temporaryBreakpoint.getLineNumber()
   139 					&& className.equals(temporaryBreakpoint.getClassName()))
   140 				{
   141 					// destroy the temporary breakpoint
   142 					int numberOfBreakpoints = breakpoints.getNumberOfBreakpoints();
   143 					boolean canDestroy = true;
   144 
   145 					for(int i = 0; i < numberOfBreakpoints; i++)
   146 					{
   147 						Breakpoint breakpoint = breakpoints.getBreakpoint(i);
   148 
   149 						if (breakpoint.getLineNumber() == temporaryBreakpoint.getLineNumber()
   150 							&& breakpoint.getClassName() == temporaryBreakpoint.getClassName()
   151 							&& breakpoint.isEnabled() && breakpoint.isValid())
   152 							canDestroy = false;
   153 					}
   154 
   155 					if (canDestroy)
   156 					{
   157 						boolean success = true; // breakpoint was successfully removed from the remoteDebugger (if exists)
   158 
   159 						try
   160 						{
   161 							RemoteClass rc = remoteDebugger.findClass(className);
   162 									String result;
   163 
   164 							if (rc != null)
   165 							{
   166 								result = rc.clearBreakpointLine(lineNumber);
   167 										if (!result.equals(""))
   168 											success = false;
   169 							}
   170 							else
   171 								success = false;
   172 						}
   173 						catch(Exception e)
   174 						{
   175 							e.printStackTrace();
   176 							success = false;
   177 						}
   178 
   179 						// if the breakpoint was succesfully removed from the debugger, we must also remove breakpoint
   180 						// line (if exists)
   181 						if (!success)
   182 						{
   183 							TopLevel.getOutput().show();
   184 							TopLevel.getOutput().println("temporary breakpoint \""+className+":"+lineNumber+"\" cannot be removed");
   185 						}
   186 						else
   187 							temporaryBreakpoint = null;
   188 					}
   189 				}
   190 
   191 			// get a source and a position on which we have stopped
   192 			Source s = null;
   193 
   194 			s = new Source(className, false);
   195 
   196 			//JARDA - az Jaroslav opravi editor, nebude se mazat current line
   197 			//Position oldPosition = currentPosition;
   198 			currentPosition = TopLevel.getCurrentSnapshot().getPosition(s, lineNumber-1).beginOfLine();
   199 			JavaEditorFrame jef = TopLevel.showEditor(s, currentPosition, true);
   200 
   201 			//if (oldPosition != null)
   202 			//	Block.line(oldPosition).redraw();
   203 
   204 			Block.line(currentPosition).redraw();
   205 		}
   206 		catch (IOException e)
   207 		{
   208 			TopLevel.getOutput().show();
   209 			TopLevel.getOutput().println("class '"+className+"' not found");
   210 		}
   211 		catch (NoSuchElementException e)
   212 		{
   213 			TopLevel.getOutput().show();
   214 			TopLevel.getOutput().println("cannot get debug info for the class '"+className+"'");
   215 			TopLevel.getOutput().println("    ( is the class compiled with the -g option? )");
   216 		}
   217 
   218 		watches.updateContent();
   219 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
   220 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
   221 		threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
   222 		//threadsView.highlightThread(t);
   223 	}
   224 
   225 	/**
   226 	 * Implementation of the exceptionEvent from the DebuggerCallback
   227 	 */
   228 	public void exceptionEvent(RemoteThread t, String s) throws Exception
   229 	{
   230 		Output output = TopLevel.getOutput();
   231 
   232 		output.show();
   233 		output.println("exception in thread \""+t.getName()+"\": "+s);
   234 	}
   235 
   236 	/**
   237 	 * Implementation of the threadDeathEvent from the DebuggerCallback
   238 	 */
   239 	public void threadDeathEvent(RemoteThread t)
   240 	{
   241 		if (t == currentThread)
   242 			internalFinishDebugging();
   243 		else
   244 			threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
   245 	}
   246 
   247 	/**
   248 	 * Implementation of the quitEvent from the DebuggerCallback
   249 	 */
   250 	public void quitEvent()
   251 	{
   252 		internalFinishDebugging();
   253 	}
   254 
   255 	/**
   256 	 * Implementation of the printToConsole from the DebuggerCallback
   257 	 */
   258 	public synchronized void printToConsole(String s)
   259 	{
   260 		TopLevel.getOutput().println(s);
   261 	}
   262 
   263 	/**
   264 	 * Implementation of the getForeground method from the BackgroundCallback
   265 	 */
   266 	public Color getForeground()
   267 	{
   268 		return foregroundColor;
   269 	}
   270 
   271 	/**
   272 	 * Implementation of the getBackground method from the BackgroundCallback
   273 	 */
   274 	// musi se delat efektivneji - nejlepe hashovat , zatim se to dela v O(n) !!!
   275 	public Color getBackground(Position p)
   276 	{
   277 		if (debuggingSession)
   278 			if (currentPosition != null)
   279 				if (p.sameLine(currentPosition))
   280 				{
   281 					foregroundColor = currentLineForegroundColor;
   282 					return currentLineBackgroundColor;
   283 				}
   284 
   285 		// jeste se musime podivat, zda to neni breakpoint line
   286 		PositionInfo pInfo = TopLevel.getCurrentSnapshot().getPositionInfo(p);
   287 		String className = pInfo.getSource().getName();
   288 		int lineNumber = pInfo.getLine();
   289 
   290 		int numberOfBreakpoints = breakpoints.getNumberOfBreakpoints();
   291 
   292 		for(int i = 0; i < numberOfBreakpoints; i++)
   293 			if (breakpoints.getBreakpoint(i).getLineNumber()-1 == lineNumber)
   294 				if (breakpoints.getBreakpoint(i).getClassName().compareTo(className) == 0)
   295 					if (breakpoints.getBreakpoint(i).isValid() && breakpoints.getBreakpoint(i).isEnabled())
   296 					{
   297 						foregroundColor = breakpointLineForegroundColor;
   298 						return breakpointLineBackgroundColor;
   299 					}
   300 
   301 		return null;
   302 	}
   303 
   304 	/**
   305 	 * Implementation of the colorsChanged from the XFColorCallback
   306 	 */
   307 	public void colorsChanged()
   308 	{
   309 	   currentLineBackgroundColor = XFColor.getBgColor(XFColor.CurrentLine);
   310 		currentLineForegroundColor = XFColor.getFgColor(XFColor.CurrentLine);
   311 		breakpointLineBackgroundColor = XFColor.getBgColor(XFColor.BreakpointLine);
   312 		breakpointLineForegroundColor = XFColor.getFgColor(XFColor.BreakpointLine);
   313 	}
   314 
   315 	/**
   316 	 * Implementation of the loadProperies from the XelfiOptions
   317 	 */
   318 	public void loadProperties(EnhProperties properties)
   319 	{
   320 		options.getProperties(properties);
   321 
   322 		watches.getProperties(properties);
   323 		breakpoints.getProperties(properties);
   324 	}
   325 
   326 	/**
   327 	 * Implementation of the storeProperties from the XelfiOptions
   328 	 */
   329 	public void storeProperties(EnhProperties properties)
   330 	{
   331 		options.putProperties(properties);
   332 
   333 		watches.putProperties(properties);
   334 		breakpoints.putProperties(properties);
   335 	}
   336 
   337 	/**
   338 	 * Implementation of the getPanel from the XelfiOptions
   339 	 */
   340 	public Panel getPanel()
   341 	{
   342 		return new DebuggerOptionsPanel(options);
   343 	}
   344 
   345 	/**
   346 	 * Implementation of the getTabName from the XelfiOptions
   347 	 */
   348 	public String getTabName()
   349 	{
   350 		return "Debug";
   351 	}
   352 
   353 	/**
   354 	 * Implementation of the onOK from the XelfiOptions
   355 	 */
   356 	public void onOK(Panel p)
   357 	{
   358 		options = ((DebuggerOptionsPanel)p).getDebuggerOptions();
   359 
   360 		watches.updateContent();
   361 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
   362 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
   363 	}
   364 
   365 	/**
   366 	 * Handles Debug|Go command.
   367 	 */
   368 	public void go()
   369 	{
   370 		canEnableGoFlag = false;
   371 		canEnableGoToCursorFlag = false;
   372 
   373 		TopLevel.getMenu().disableItem(MainMenu.miDebugGo);
   374 		TopLevel.getMenu().disableItem(MainMenu.miDebugGoCursor);
   375 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceOver);
   376 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceInto);
   377 
   378 		if (!debuggingSession)
   379 		{
   380 			try
   381 			{
   382 				if (!initDebuggingSession())
   383 				{
   384 					finishDebugging();
   385 					/*canEnableGoFlag = false;
   386 					canEnableGoToCursorFlag = false;
   387 
   388 					TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
   389 					TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);*/
   390 
   391 					return;
   392 				}
   393 
   394 				if (remoteDebugger.listBreakpoints().length == 0)
   395 					if (!setDefaultBreakpoint())
   396 					{
   397 						finishDebugging();
   398 						/*canEnableGoFlag = false;
   399 						canEnableGoToCursorFlag = false;
   400 
   401 						TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
   402 						TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);*/
   403 
   404 						return;
   405 					}
   406 
   407 
   408                             StringTokenizer st = new StringTokenizer(RunOptions.getArguments());
   409                             int nTokens = st.countTokens();
   410                             String args[] = new String[1+nTokens];
   411 
   412                             args[0] = new String(getClassToDebug());
   413                             for(int i = 1; i <= nTokens; i++)
   414                                 args[i] = st.nextToken();
   415 
   416                             currentThreadGroup = remoteDebugger.run(1+nTokens, args);
   417 			    // setThread(1);
   418 			}
   419 			catch(Exception e)
   420 			{
   421 				e.printStackTrace();
   422 			};
   423 		}
   424 		else
   425 		{
   426 			if (currentThread == null)
   427 			{
   428 				System.err.println("nothing suspended");
   429 				return;
   430 			}
   431 
   432 			try
   433 			{
   434 				currentThread.cont();
   435 			}
   436 			catch(Exception e)
   437 			{
   438 				e.printStackTrace();
   439 			};
   440 
   441 			currentThread.resetCurrentFrameIndex();
   442 		}
   443 
   444 		// JARDA - dokud Jarda neopravi, bude se to delat az v breakpointEvent
   445 		// decolor the current line
   446 		if (currentPosition != null)
   447 		{
   448 			Position oldPosition = currentPosition;
   449 
   450 			currentPosition = null;
   451 			Block.line(oldPosition).redraw();
   452 		}
   453 	}
   454 
   455 	/**
   456 	 * Handles Debug|GoToCursor command.
   457 	 */
   458 	public void goToCursor(Source s, Position p)
   459 	{
   460 		canEnableGoFlag = false;
   461 		canEnableGoToCursorFlag = false;
   462 
   463 		TopLevel.getMenu().disableItem(MainMenu.miDebugGo);
   464 		TopLevel.getMenu().disableItem(MainMenu.miDebugGoCursor);
   465 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceOver);
   466 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceInto);
   467 
   468 		if (!debuggingSession)
   469 		{
   470 			try
   471 			{
   472 				if (!initDebuggingSession())
   473 				{
   474 					canEnableGoFlag = false;
   475 					canEnableGoToCursorFlag = false;
   476 
   477 					TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
   478 					TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);
   479 
   480 					return;
   481 				}
   482 
   483 				setTemporaryBreakpoint(s, p);
   484 
   485                             StringTokenizer st = new StringTokenizer(RunOptions.getArguments());
   486                             int nTokens = st.countTokens();
   487                             String args[] = new String[1+nTokens];
   488 
   489                             args[0] = new String(getClassToDebug());
   490                             for(int i = 1; i <= nTokens; i++)
   491                                 args[i] = st.nextToken();
   492 
   493                             currentThreadGroup = remoteDebugger.run(1+nTokens, args);
   494                             // setThread(1);
   495 			}
   496 			catch(Exception e)
   497 			{
   498 				e.printStackTrace();
   499 			};
   500 		}
   501 		else
   502 		{
   503 			if (currentThread == null)
   504 			{
   505 				System.err.println("nothing suspended");
   506 				return;
   507 			}
   508 
   509 			try
   510 			{
   511 				setTemporaryBreakpoint(s, p);
   512 				currentThread.cont();
   513 			}
   514 			catch(Exception e)
   515 			{
   516 				e.printStackTrace();
   517 			};
   518 
   519 			currentThread.resetCurrentFrameIndex();
   520 		}
   521 
   522 		// JARDA - dokud Jarda neopravi, bude se to delat az v breakpointEvent
   523 		// decolor the current line
   524 		if (currentPosition != null)
   525 		{
   526 			Position oldPosition = currentPosition;
   527 
   528 			currentPosition = null;
   529 			Block.line(oldPosition).redraw();
   530 		}
   531 	}
   532 
   533 	void internalFinishDebugging()
   534 	{
   535 		canEnableGoFlag = true;
   536 		canEnableGoToCursorFlag = true;
   537 
   538 		Position oldPosition = currentPosition;
   539 
   540 		doneDebuggingSession(false);
   541 
   542 		currentPosition = null;
   543 		if (oldPosition != null)
   544 			Block.line(oldPosition).redraw();
   545 
   546 		watches.updateContent();
   547 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
   548 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
   549 		threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
   550 	}
   551 
   552 	/**
   553 	 * Handles Debug|FinishDebugging command.
   554 	 */
   555 	public void finishDebugging()
   556 	{
   557 		canEnableGoFlag = true;
   558 		canEnableGoToCursorFlag = true;
   559 
   560 		Position oldPosition = currentPosition;
   561 
   562 		doneDebuggingSession(true);
   563 
   564 		currentPosition = null;
   565 		if (oldPosition != null)
   566 			Block.line(oldPosition).redraw();
   567 
   568 		watches.updateContent();
   569 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
   570 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
   571 		threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
   572 	}
   573 
   574 	/**
   575 	 * Handles Debug|RestartDebugging command.
   576 	 */
   577 	public void restartDebugging()
   578 	{
   579 		try
   580 		{
   581 			finishDebugging();
   582 			go();
   583 		}
   584 		catch(Exception e)
   585 		{
   586 			e.printStackTrace();
   587 		}
   588 	}
   589 
   590 	/**
   591 	 * Handles Debug|TraceOver command.
   592 	 */
   593 	public void traceOver()
   594 	{
   595 		canEnableGoFlag = false;
   596 		canEnableGoToCursorFlag = false;
   597 
   598 		TopLevel.getMenu().disableItem(MainMenu.miDebugGo);
   599 		TopLevel.getMenu().disableItem(MainMenu.miDebugGoCursor);
   600 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceOver);
   601 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceInto);
   602 
   603 		if (currentThread == null)
   604 		{
   605 			System.err.println("nothing suspended");
   606 			return;
   607 		}
   608 
   609 		try
   610 		{
   611 			currentThread.next();
   612 		}
   613 		catch(IllegalAccessError e)
   614 		{
   615 			//"Current thread is not at breakpoint."
   616 			e.printStackTrace();
   617 		}
   618 		catch(Exception e)
   619 		{
   620 			e.printStackTrace();
   621 		}
   622 
   623 	// JARDA - dokud Jarda neopravi, bude se to delat az v breakpointEvent
   624 		// decolor the current line
   625 		if (currentPosition != null)
   626 		{
   627 			Position oldPosition = currentPosition;
   628 
   629 			currentPosition = null;
   630 			Block.line(oldPosition).redraw();
   631 		}
   632 	}
   633 
   634 	/**
   635 	 * Handles Debug|TraceInto command.
   636 	 */
   637 	public void traceInto()
   638 	{
   639 		canEnableGoFlag = false;
   640 		canEnableGoToCursorFlag = false;
   641 
   642 		TopLevel.getMenu().disableItem(MainMenu.miDebugGo);
   643 		TopLevel.getMenu().disableItem(MainMenu.miDebugGoCursor);
   644 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceOver);
   645 		TopLevel.getMenu().disableItem(MainMenu.miDebugTraceInto);
   646 
   647 		if (currentThread == null)
   648 		{
   649 			System.err.println("nothing suspended");
   650 			return;
   651 		}
   652 
   653 		try
   654 		{
   655 			currentThread.step(true);
   656 		}
   657 		catch(IllegalAccessError e)
   658 		{
   659 			//"Current thread is not at breakpoint."
   660 			e.printStackTrace();
   661 		}
   662 		catch(Exception e)
   663 		{
   664 			e.printStackTrace();
   665 		}
   666 
   667 		// JARDA - dokud Jarda neopravi, bude se to delat az v breakpointEvent
   668 		// decolor the current line
   669 		if (currentPosition != null)
   670 		{
   671 			Position oldPosition = currentPosition;
   672 
   673 			currentPosition = null;
   674 			Block.line(oldPosition).redraw();
   675 		}
   676 	}
   677 
   678 	/**
   679 	 * Handles Debug|ToggleBreakpoint command.
   680 	 */
   681 	public void toggleBreakpoint(Source s, Position p)
   682 	{
   683 		PositionInfo pInfo = TopLevel.getCurrentSnapshot().getPositionInfo(p);
   684 		String className = pInfo.getSource().getName();
   685 		int lineNumber = pInfo.getLine()+1;
   686 		int numberOfBreakpoints = breakpoints.getNumberOfBreakpoints();
   687 		int index = -1;
   688 
   689 		for(int i = 0; i < numberOfBreakpoints; i++)
   690 		{
   691 			Breakpoint breakpoint = breakpoints.getBreakpoint(i);
   692 
   693 			if (className.equals(breakpoint.getClassName()) &&
   694 				lineNumber == breakpoint.getLineNumber())
   695 			{
   696 				index = i;
   697 				break; // breakpoint is already set
   698 			}
   699 		}
   700 
   701 		if (index == -1)
   702 			breakpoints.addBreakpoint(new Breakpoint(className, lineNumber));
   703 		else
   704 			breakpoints.removeBreakpoint(index);
   705 	}
   706 
   707 	/**
   708 	 * Handles Debug|AddWatch command.
   709 	 */
   710 	public void addWatch()
   711 	{
   712 		watches.getView().addWatch();
   713 	}
   714 
   715 	/**
   716 	 * Initializes the debugging session.
   717 	 * Returns false if it is not possible to continue (don't know which class to start).
   718 	 */
   719 	boolean initDebuggingSession() throws Exception
   720 	{
   721 		TopLevel.getOutput().clear();
   722 
   723 		if (getClassToDebug().equals(""))
   724 		{
   725 			TopLevel.getOutput().show();
   726 			TopLevel.getOutput().println("don't know which class to start");
   727 			return false;
   728 		}
   729 
   730 		TopLevel.getMenu().enableItem(MainMenu.miDebugFinish);
   731 		TopLevel.getMenu().enableItem(MainMenu.miDebugRestart);
   732 
   733 		try
   734 		{
   735 			TopLevel.getOutput().show();
   736 			TopLevel.getOutput().println("debugger session is starting ...");
   737 
   738 			remoteDebugger = new RemoteDebugger("", this, false);
   739 			remoteDebuggers.addElement(remoteDebugger);
   740 
   741 			TopLevel.getOutput().clear();
   742 			TopLevel.getOutput().println("debugger session has started");
   743 		}
   744 		catch(Exception e)
   745 		{
   746 			e.printStackTrace();
   747 		}
   748 
   749 		int numberOfBreakpoints = breakpoints.getNumberOfBreakpoints();
   750 
   751 		debuggingSession = true;
   752 		for(int i = 0; i < numberOfBreakpoints; i++)
   753 		{
   754 			Breakpoint breakpoint = breakpoints.getBreakpoint(i);
   755 
   756 			if (breakpoint.isEnabled())
   757 				addBreakpoint(breakpoint);
   758 		}
   759 
   760 		breakpoints.updateContent();
   761 		return true;
   762 	}
   763 
   764 	/**
   765 	 * Closes the debugging session.
   766 	 */
   767 	void doneDebuggingSession(boolean closeDebugger)
   768 	{
   769 		try
   770 		{
   771 			if (remoteDebugger != null)
   772 			{
   773 				// stop all threads
   774 				RemoteThreadGroup[] rtg = getThreadGroups();
   775 
   776 				if (rtg != null)
   777 					for(int i = 0; i < rtg.length; i++)
   778 					{
   779 						try
   780 						{
   781 							//without system thread group
   782 							if (rtg[i].getName().equals("system"))
   783 								continue;
   784 
   785 							RemoteThread rt[] = rtg[i].listThreads(true);
   786 							if (rt == null)
   787 								continue;
   788 
   789 							for(int j = 0; j < rt.length; j++)
   790 								if (rt[j] != null)
   791 									rt[j].stop();
   792 						}
   793 						catch(Exception e)
   794 						{
   795 							//e.printStackTrace();
   796 						}
   797 					}
   798 
   799              if (closeDebugger)
   800              {
   801                  remoteDebugger.close();
   802                  remoteDebuggers.removeElement(remoteDebugger);
   803              }
   804              else
   805                  remoteDebuggers.removeElement(remoteDebugger);
   806 
   807 				if (debuggingSession)
   808 				{
   809 					debuggingSession = false;
   810 
   811 					TopLevel.getOutput().show();
   812 					TopLevel.getOutput().println("debugger session has finished");
   813 				}
   814 
   815 				currentThread = null;
   816 				currentThreadGroup = null;
   817 				remoteDebugger = null;
   818 			}
   819 
   820 			TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
   821 			TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);
   822 			TopLevel.getMenu().disableItem(MainMenu.miDebugFinish);
   823 			TopLevel.getMenu().disableItem(MainMenu.miDebugRestart);
   824 
   825 			TopLevel.getMenu().disableItem(MainMenu.miDebugTraceOver);
   826 			TopLevel.getMenu().disableItem(MainMenu.miDebugTraceInto);
   827 		}
   828 		catch(Exception e)
   829 		{ }
   830 	}
   831 
   832 	/**
   833 	 * This method is called by the CallStackView when
   834 	 * a stack frame is chosen.
   835 	 */
   836 	void stackFrameChosen(RemoteStackFrame rsf)
   837 	{
   838 		String className = null;
   839 
   840 		try
   841 		{
   842 			RemoteStackFrame.Name rc = rsf.getRemoteClass();
   843 
   844 			if (rc == null)
   845 				System.out.println("invalid stack frame");
   846 
   847 			try
   848 			{
   849 				className = rc.getName();
   850 			}
   851 			catch(Exception e)
   852 			{
   853 				className = null;
   854 				e.printStackTrace();
   855 			}
   856 
   857 			int lineNumber = rsf.getLineNumber();
   858 
   859 			if (className == null)
   860 				System.out.println("invalid class name");
   861 
   862 			// get a source and a position
   863     		Source s = new Source(className, false);
   864 			Position p = TopLevel.getCurrentSnapshot().getPosition(s, lineNumber-1).beginOfLine();
   865 
   866 			TopLevel.showEditor(s, p, true);
   867 		}
   868 		catch (IOException e)
   869 		{
   870 			TopLevel.getOutput().show();
   871 			TopLevel.getOutput().println("source code for class '"+className+"' not found");
   872 		}
   873 	}
   874 
   875 	/**
   876 	 * Called when final clean up is neccessary.
   877 	 */
   878 	public void shutdown()
   879 	{
   880 		for(int i = 0; i < remoteDebuggers.size(); i++)
   881 		{
   882 			try
   883 			{
   884 				remoteDebugger = (RemoteDebugger)remoteDebuggers.elementAt(i);
   885 
   886 				// stop all threads
   887 				RemoteThreadGroup[] rtg = getThreadGroups();
   888 
   889 				if (rtg != null)
   890 					for(int k = 0; k < rtg.length; k++)
   891 					{
   892 						try
   893 						{
   894 							//without system thread group
   895 							if (rtg[k].getName().equals("system"))
   896 								continue;
   897 
   898 							RemoteThread rt[] = rtg[k].listThreads(true);
   899 							if (rt == null)
   900 								continue;
   901 
   902 							for(int j = 0; j < rt.length; j++)
   903 								if (rt[j] != null)
   904 									rt[j].stop();
   905 						}
   906 						catch(Exception e)
   907 						{
   908 							e.printStackTrace();
   909 						}
   910 					}
   911 
   912             remoteDebugger.close();
   913             remoteDebuggers.removeElement(remoteDebugger);
   914 				//((RemoteDebugger)remoteDebuggers.elementAt(i)).close();
   915 			}
   916 			catch(Exception e)
   917 			{
   918 				//e.printStackTrace();
   919 				//because some RemoteDebuggers are already closed
   920          }
   921 		}
   922 	}
   923 
   924 	/**
   925 	 * Sets the default breakpoint (on method <main class>.main).
   926 	 */
   927 	boolean setDefaultBreakpoint()
   928 	{
   929 		boolean success = true; // breakpoint was successfully added into the remoteDebugger (if exists)
   930 
   931 		try
   932 		{
   933 			RemoteClass rc = remoteDebugger.findClass(getClassToDebug());
   934 			String result;
   935 
   936 			if (rc != null)
   937 			{
   938 				RemoteField rf = rc.getMethod("main");
   939 
   940 				if (rf != null)
   941 				{
   942 					result = rc.setBreakpointMethod(rf);;
   943 					if (!result.equals(""))
   944 						success = false;
   945 				}
   946 				else
   947 					success = false;
   948 			}
   949 			else
   950 				success = false;
   951 		}
   952 		catch(Exception e)
   953 		{
   954 			e.printStackTrace();
   955 			success = false;
   956 		}
   957 
   958 		if (!success)
   959 		{
   960 			TopLevel.getOutput().show();
   961 			TopLevel.getOutput().println("default breakpoint \""+getClassToDebug()+".main\" cannot be set");
   962 			TopLevel.getOutput().println("    ( is the class compiled with the -g option? )");
   963 			return false;
   964 		}
   965 		else
   966 			return true;
   967 	}
   968 
   969 	/**
   970 	 * Sets the temporary breakpoint.
   971 	 */
   972 	void setTemporaryBreakpoint(Source s, Position p)
   973 	{
   974 		PositionInfo pInfo = TopLevel.getCurrentSnapshot().getPositionInfo(p);
   975 		String className = pInfo.getSource().getName();
   976 		int lineNumber = pInfo.getLine()+1;
   977 
   978 		boolean success = true; // breakpoint was successfully added into the remoteDebugger (if exists)
   979 
   980 		try
   981 		{
   982 			RemoteClass rc = remoteDebugger.findClass(className);
   983 			String result;
   984 
   985 		if (rc != null)
   986 		{
   987 			result = rc.setBreakpointLine(lineNumber);
   988 
   989 			if (!result.equals(""))
   990 			{
   991 				rc.clearBreakpointLine(lineNumber);
   992 				success = false;
   993 			}
   994 		}
   995 		else
   996 			success = false;
   997 		}
   998 	catch(Exception e)
   999 	{
  1000 		e.printStackTrace();
  1001 		success = false;
  1002 	}
  1003 
  1004 	if (!success)
  1005 		{
  1006 			TopLevel.getOutput().show();
  1007 			TopLevel.getOutput().println("temporary breakpoint \""+className+":"+lineNumber+"\" cannot be set");
  1008 			temporaryBreakpoint = null;
  1009 		}
  1010 		else
  1011 			temporaryBreakpoint = new Breakpoint(className, lineNumber);
  1012 	}
  1013 
  1014 	/**
  1015 	 * Returns true if the debugger allows to enable the Debug|Go command.
  1016 	 */
  1017 	public boolean canEnableGo()
  1018 	{
  1019 		return canEnableGoFlag;
  1020 	}
  1021 
  1022 	/**
  1023 	 * Returns true if the debugger allows to enable the Debug|GoToCursor command.
  1024 	 */
  1025 	public boolean canEnableGoToCursor()
  1026 	{
  1027 		return canEnableGoToCursorFlag;
  1028 	}
  1029 
  1030 	/**
  1031 	 * Called by the LocalsView class after its instance has been shown.
  1032 	 */
  1033 	void localsViewShown()
  1034 	{
  1035 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
  1036 	}
  1037 
  1038 	/**
  1039 	 * Called by the CallStackView class after its instance has been shown.
  1040 	 */
  1041 	void callStackViewShown()
  1042 	{
  1043 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
  1044 	}
  1045 
  1046 	/**
  1047 	 * Called by the ThreadsView class after its instance has been shown.
  1048 	 */
  1049 	void threadsViewShown()
  1050 	{
  1051 		threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
  1052 	}
  1053 
  1054 	/**
  1055 	 * Returns the current value of the variable specified by the name variableName
  1056 	 */
  1057 	String getCurrentValue(String variableName)
  1058 	{
  1059 		if (!debuggingSession)
  1060 			return "is not defined";
  1061 
  1062 		if (currentThread == null)
  1063 			return "is not defined";
  1064 
  1065 		try
  1066 		{
  1067 			StringTokenizer st = new StringTokenizer(variableName, ".[]", true);
  1068 
  1069 			if (!st.hasMoreTokens())
  1070 				return "invalid expression";
  1071 
  1072   			String token = st.nextToken();
  1073 			RemoteStackVariable rsv = currentThread.getStackVariable(token);
  1074 
  1075 			if (rsv == null)
  1076 				return "is not defined";
  1077 			if (!rsv.inScope())
  1078 				return "is not in scope.";
  1079 
  1080 			RemoteValue obj = rsv.getValue();
  1081 
  1082 			if (obj == null)
  1083 				return "null"; // is it correct?
  1084 
  1085 			while (st.hasMoreTokens())
  1086 			{
  1087 				token = st.nextToken();
  1088 				if (token.equals("["))
  1089 				{
  1090 					if (!st.hasMoreTokens())
  1091 						return "index missing";
  1092 					token = st.nextToken();
  1093 
  1094 					if (!st.hasMoreTokens())
  1095 						return "invalid expression";
  1096 					if (!st.nextToken().equals("]"))
  1097 						return "invalid expression";
  1098 
  1099 					int index;
  1100 
  1101 					try
  1102 					{
  1103 						try
  1104 						{
  1105 							index = Integer.valueOf(token).intValue();
  1106 						}
  1107 						catch (NumberFormatException e)
  1108 						{
  1109 							index = Integer.valueOf(getCurrentValue(token)).intValue();
  1110 						}
  1111 
  1112 						obj = ((RemoteArray)obj).getElement(index);
  1113 
  1114 						if (obj == null)
  1115 							return "null"; // is it correct?
  1116 					}
  1117 					catch (NumberFormatException e)
  1118 					{
  1119 						return "invalid index";
  1120 					}
  1121 					catch (ArrayIndexOutOfBoundsException e)
  1122 					{
  1123 						return "out of bounds";
  1124 					}
  1125 					catch (ClassCastException e)
  1126 					{
  1127 						return "is not an array element";
  1128 					}
  1129 				}
  1130 
  1131 				if (token.equals("."))
  1132 				{
  1133 					if (!st.hasMoreTokens())
  1134 						return "field missing";
  1135 					token = st.nextToken();
  1136 
  1137 					try
  1138 					{
  1139 						obj = ((RemoteObject)obj).getFieldValue(token);
  1140 
  1141 						if (obj == null)
  1142 							return "null"; // is it correct?
  1143 					}
  1144 					catch (ClassCastException e)
  1145 					{
  1146 						return "is not a class field";
  1147 					}
  1148 				}
  1149 			}
  1150 
  1151 			return getCurrentValue(obj, options.getDepthOfRecursiveWatching());
  1152 		}
  1153 		catch(Exception e)
  1154 		{
  1155 			e.printStackTrace();
  1156 			return "";
  1157 		}
  1158 	}
  1159 
  1160 	/**
  1161 	 * Returns the string containing a value of the RemoteValue instance.
  1162 	 * Depth - how deep we can scan the value (it must be 0 at least).
  1163 	 */
  1164 	String getCurrentValue(RemoteValue obj, int depth)
  1165 	{
  1166 		if (obj == null)
  1167 			return "null";
  1168 
  1169 		if (obj instanceof RemoteChar)
  1170 			return "'"+obj.toString()+"'";
  1171 
  1172 		if (obj instanceof RemoteString)
  1173 			return "\""+obj.toString()+"\"";
  1174 
  1175 		if (obj instanceof RemoteArray)
  1176 		{
  1177 			if (depth == 0)
  1178 				return "[...]"; // don't continue in recursive watching
  1179 				
  1180 			RemoteValue elements[];
  1181 
  1182 			try
  1183 			{
  1184 				elements = ((RemoteArray)obj).getElements();
  1185 			}
  1186 			catch(Exception e)
  1187 			{
  1188 				e.printStackTrace();
  1189 				return "?";
  1190 			}
  1191 
  1192 			String returnValue = "[";
  1193 
  1194 			for(int i = 0; i < elements.length-1; i++)
  1195 				if (options.showArrayIndexes())
  1196 					returnValue += i+": "+getCurrentValue(elements[i], depth-1)+", ";
  1197 				else
  1198 					returnValue += getCurrentValue(elements[i], depth-1)+", ";
  1199 
  1200 			if (elements.length > 0)
  1201 				if (options.showArrayIndexes())
  1202 					returnValue += (elements.length-1)+": "+getCurrentValue(elements[elements.length-1], depth-1)+"]";
  1203 				else
  1204 					returnValue += getCurrentValue(elements[elements.length-1], depth-1)+"]";
  1205 			else
  1206 				returnValue += "]";
  1207 
  1208 			return returnValue;
  1209 		}
  1210 
  1211 		if (obj instanceof RemoteObject)
  1212 		{
  1213 			if (depth == 0)
  1214 				return "{...}"; // don't continue in recursive watching
  1215 				
  1216 			RemoteObject ro = (RemoteObject)obj;
  1217 			RemoteField fields[];
  1218 
  1219 			try
  1220 			{
  1221 				fields = ro.getFields();
  1222 			}
  1223 			catch(Exception e)
  1224 			{
  1225 				e.printStackTrace();
  1226 				return "?";
  1227 			}
  1228 
  1229 			String returnValue = "{";
  1230 			String fieldName;
  1231 			RemoteValue fieldValue;
  1232 
  1233 			if (fields.length == 0)
  1234 				return returnValue+"}";
  1235 
  1236 			for(int i = 0; i < fields.length-1; i++)
  1237 			{
  1238 				fieldName = fields[i].getName();
  1239 				try
  1240 				{
  1241 					fieldValue = ro.getFieldValue(fieldName);
  1242 					returnValue += fieldName+": "+getCurrentValue(fieldValue, depth-1)+", ";
  1243 				}
  1244 				catch(Exception e)
  1245 				{
  1246 					returnValue += fieldName+": ?, ";
  1247 				}
  1248 			}
  1249   
  1250 			fieldName = fields[fields.length-1].getName();
  1251 			try
  1252 			{
  1253 				fieldValue = ro.getFieldValue(fieldName);
  1254 				returnValue = returnValue+fieldName+": "+getCurrentValue(fieldValue, depth-1)+"}";
  1255 			}
  1256 			catch(Exception e)
  1257 			{
  1258 				returnValue = returnValue+fieldName+": ?}";
  1259 			}
  1260 
  1261 			return returnValue;
  1262 		}
  1263 
  1264 		// process the RemoteThread and RemoteTreadGroup instances
  1265 		// ...
  1266 		
  1267 		return obj.toString();
  1268 	}
  1269 
  1270 	/**
  1271 	 * Returns the name of the class which will be started in the debugger
  1272 	 * (or "").
  1273 	 */
  1274 	String getClassToDebug()
  1275         {
  1276 		String returnValue = RunOptions.getMainClass();
  1277 
  1278 		if (returnValue != null)
  1279 			return returnValue;
  1280 		else
  1281 			return "";
  1282 	}
  1283 
  1284 	/**
  1285 	 * This method is called by the Breakpoints class after a breakpoint
  1286 	 * has been added into the breakpoints document or after a breakpoint
  1287 	 * has been successfully enabled in the breakpoints document.
  1288 	 * This method can change the breakpoint state from valid to invalid
  1289 	 * if it can not be added into the remote debugger.
  1290 	 * This method is also called by the Debugger class while the debugging session is starting.
  1291 	 */
  1292 	void addBreakpoint(Breakpoint breakpoint)
  1293 	{
  1294 		boolean success = true; // breakpoint was successfully added into the remoteDebugger (if exists)
  1295 
  1296 		if (debuggingSession)
  1297 		{
  1298 			try
  1299 			{
  1300 				RemoteClass rc = remoteDebugger.findClass(breakpoint.getClassName());
  1301 				String result;
  1302 
  1303 				if (rc != null)
  1304 				{
  1305 					result = rc.setBreakpointLine(breakpoint.getLineNumber());
  1306 					if (!result.equals(""))
  1307 					{
  1308 						rc.clearBreakpointLine(breakpoint.getLineNumber());
  1309 						success = false;
  1310 					}
  1311 				}
  1312 				else
  1313 					success = false;
  1314 			}
  1315 			catch(Exception e)
  1316 			{
  1317 				e.printStackTrace();
  1318 				success = false;
  1319 			}
  1320 		}
  1321 
  1322 		// if the breakpoint was succesfully enabled or added into the remote debugger,
  1323 		// we must also add breakpoint line (if possible)
  1324 		if (!success)
  1325 		{
  1326 			breakpoint.setInvalid();
  1327 			TopLevel.getOutput().show();
  1328 			TopLevel.getOutput().println("breakpoint \""+breakpoint.getClassName()+":"+breakpoint.getLineNumber()+"\" cannot be set");
  1329 
  1330 			try
  1331 			{
  1332 				Position breakpointPosition;
  1333 				JavaEditorFrame jef = TopLevel.findEditor(breakpoint.getClassName());
  1334 
  1335 				if (jef != null)
  1336 				{
  1337 					breakpointPosition = TopLevel.getCurrentSnapshot().getPosition(jef.getSource(), breakpoint.getLineNumber()-1);
  1338 					Block.line(breakpointPosition).redraw();
  1339 				}
  1340 			}
  1341 			catch (Exception e)
  1342 			{
  1343 				// mozna by se vyjimka mela jenom sezrat
  1344 				e.printStackTrace();
  1345 			}
  1346 		}
  1347 		else
  1348 		{
  1349 			breakpoint.setValid();
  1350 
  1351 			try
  1352 			{
  1353 				Position breakpointPosition;
  1354 				JavaEditorFrame jef = TopLevel.findEditor(breakpoint.getClassName());
  1355 
  1356 				if (jef != null)
  1357 				{
  1358 					breakpointPosition = TopLevel.getCurrentSnapshot().getPosition(jef.getSource(), breakpoint.getLineNumber()-1);
  1359 					Block.line(breakpointPosition).redraw();
  1360 				}
  1361 			}
  1362 			catch (Exception e)
  1363 			{
  1364 				// mozna by se vyjimka mela jenom sezrat
  1365 				e.printStackTrace();
  1366 			}
  1367 		}
  1368 	}
  1369 
  1370 	/**
  1371 	 * This method is called by the Breakpoints class after a breakpoint
  1372 	 * has been removed or disabled in the breakpoints document.
  1373 	 */
  1374 	void removeBreakpoint(String className, int lineNumber)
  1375 	{
  1376 		boolean success = true; // breakpoint was successfully removed from the remoteDebugger (if exists)
  1377 
  1378 		if (debuggingSession)
  1379 		{
  1380 			try
  1381 			{
  1382 				RemoteClass rc = remoteDebugger.findClass(className);
  1383 				String result;
  1384 
  1385 				if (rc != null)
  1386 				{
  1387 					result = rc.clearBreakpointLine(lineNumber);
  1388 					if (!result.equals(""))
  1389 						success = false;
  1390 				}
  1391 				else
  1392 					success = false;
  1393 			}
  1394 			catch(Exception e)
  1395 			{
  1396 				e.printStackTrace();
  1397 				success = false;
  1398 			}
  1399 		}
  1400 
  1401 		// if the breakpoint was succesfully removed from the debugger, we must also remove breakpoint
  1402 		// line (if exists)
  1403 		if (success)
  1404 		{
  1405 			try
  1406 			{
  1407 				Position breakpointPosition;
  1408 				JavaEditorFrame jef = TopLevel.findEditor(className);
  1409 
  1410 				if (jef != null)
  1411 				{
  1412 					breakpointPosition = TopLevel.getCurrentSnapshot().getPosition(jef.getSource(), lineNumber-1);
  1413 					Block.line(breakpointPosition).redraw();
  1414 				}
  1415 			}
  1416 			catch (Exception e)
  1417 			{
  1418 				// mozna by se vyjimka mela jenom sezrat
  1419 				e.printStackTrace();
  1420 			}
  1421 		}
  1422 	}
  1423 
  1424 	/**
  1425 	 * Returns the stack frames of the current thread
  1426 	 */
  1427 	RemoteStackFrame[] getCurrentStackFrames()
  1428 	{
  1429 		RemoteStackFrame[] rsf = null;
  1430 
  1431 		if (currentThread == null)
  1432 			return null;
  1433 
  1434 		try
  1435 		{
  1436 			rsf = currentThread.dumpStack();
  1437 		}
  1438 		catch(Exception e)
  1439 		{
  1440 			e.printStackTrace();
  1441 		}
  1442 
  1443 		return rsf;
  1444 	}
  1445 
  1446 	/**
  1447 	 * Returns the stack frame index of the current thread
  1448 	 */
  1449 	int getCurrentStackFrameIndex()
  1450 	{
  1451 		if (currentThread == null)
  1452 			return -1;
  1453 
  1454 		return currentThread.getCurrentFrameIndex();
  1455 	}
  1456 
  1457 	/**
  1458 	 * Returns the stack variables of the current thread
  1459 	 */
  1460 	RemoteStackVariable[] getStackVariables()
  1461 	{
  1462 		RemoteStackVariable[] rsv = null;
  1463 
  1464 		if (currentThread == null)
  1465 			return null;
  1466 
  1467 		try
  1468 		{
  1469 			rsv = currentThread.getStackVariables();
  1470 		}
  1471 		catch(Exception e)
  1472 		{
  1473 			e.printStackTrace();
  1474 		};
  1475 
  1476 		return rsv;
  1477 	}
  1478 
  1479 	/**
  1480 	 * Returns the current stack frame of the current thread
  1481 	 */
  1482 	RemoteStackFrame getCurrentStackFrame()
  1483 	{
  1484 		RemoteStackFrame rsf = null;
  1485 
  1486 		if (currentThread == null)
  1487 			return null;
  1488 
  1489 		try
  1490 		{
  1491 			 rsf = currentThread.getCurrentFrame();
  1492 		}
  1493 		catch(Exception e)
  1494 		{
  1495 			 e.printStackTrace();
  1496 		};
  1497 
  1498 		return rsf;
  1499 	}
  1500 
  1501 	/**
  1502 	 * Returns the thread groups
  1503 	 */
  1504 	RemoteThreadGroup[] getThreadGroups()
  1505 	{
  1506 		RemoteThreadGroup[] rtg = null;
  1507 
  1508 		if (remoteDebugger == null)
  1509 			return null;
  1510 
  1511 		try
  1512 		{
  1513 			rtg = remoteDebugger.listThreadGroups(null);
  1514 		}
  1515 		catch(Exception e)
  1516 		{
  1517 			e.printStackTrace();
  1518 		};
  1519 
  1520 		return rtg;
  1521 	}
  1522 
  1523 	/**
  1524 	 * Returns the current thread
  1525 	 */
  1526 	RemoteThread getCurrentThread()
  1527 	{
  1528 		return currentThread;
  1529 	}
  1530 
  1531 	/**
  1532 	 * Returns the Watches document
  1533 	 */
  1534 	public Watches getWatches()
  1535 	{
  1536 		return watches;
  1537 	}
  1538 
  1539 	/**
  1540 	 * Returns the Breakpoints document
  1541 	 */
  1542 	public Breakpoints getBreakpoints()
  1543 	{
  1544 		return breakpoints;
  1545 	}
  1546 
  1547 	/**
  1548 	 * Returns the LocalsView on the Debugger
  1549 	 */
  1550 	public LocalsView getLocalsView()
  1551 	{
  1552 		return localsView;
  1553 	}
  1554 
  1555 	/**
  1556 	 * Returns the CallStackView on the Debugger
  1557 	 */
  1558 	public CallStackView getCallStackView()
  1559 	{
  1560 		return callStackView;
  1561 	}
  1562 
  1563 	/**
  1564 	 * Returns the ThreadsView on the Debugger
  1565 	 */
  1566 	public ThreadsView getThreadsView()
  1567 	{
  1568 		return threadsView;
  1569 	}
  1570 
  1571 	////////////////////////////////////////////////////////////////
  1572 
  1573 	/*	void threadChosen(RemoteThreadGroup tg, RemoteThread t)
  1574 	{
  1575 		canEnableGoFlag = true;
  1576 		canEnableGoToCursorFlag = true;
  1577 
  1578 		TopLevel.getMenu().enableItem(MainMenu.miDebugGo);
  1579 		TopLevel.getMenu().enableItem(MainMenu.miDebugGoCursor);
  1580 		TopLevel.getMenu().enableItem(MainMenu.miDebugTraceOver);
  1581 		TopLevel.getMenu().enableItem(MainMenu.miDebugTraceInto);
  1582 
  1583 		RemoteStackFrame[] stack;
  1584 
  1585 		try
  1586 		{
  1587 			stack = t.dumpStack();
  1588 		}
  1589 		catch(Exception e)
  1590 		{
  1591 			e.printStackTrace();
  1592 			return;
  1593 		}
  1594 
  1595 		currentThreadGroup = tg;
  1596 
  1597 		if (stack.length > 0)
  1598 		{
  1599 			for(int i = 0; i < stack.length; i++)
  1600 			{
  1601 				System.out.println(i+"   "+stack[i].toString());
  1602 			}
  1603 			currentThread = t;
  1604 		}
  1605 		else
  1606 		{
  1607 			TopLevel.getOutput().show();
  1608 			TopLevel.getOutput().println("invalid thread specified in breakpoint");
  1609 		}
  1610 
  1611 		StringTokenizer st = new StringTokenizer(stack[getCurrentStackFrameIndex()].toString(), ".()");
  1612 		String className = new String();
  1613 		int lineNumber = -1;
  1614 		int nTokens = st.countTokens();
  1615 
  1616 		for(int i = 3; i < nTokens; i++) // n-3 times
  1617 			className = className+st.nextToken()+".";
  1618 
  1619 		className += st.nextToken();
  1620 
  1621 		st.nextToken();
  1622 		st.nextToken(":");
  1623 		lineNumber = Integer.valueOf(st.nextToken(":)")).intValue();
  1624 
  1625 		try
  1626 		{
  1627 			// get a source and a position on which we stopped
  1628 			Source s = null;
  1629 
  1630 			s = new Source(className, false);
  1631 
  1632 	// JARDA - az Jaroslav opravi editor, nebude se mazat current line
  1633 			Position oldPosition = currentPosition;
  1634 			currentPosition = TopLevel.getCurrentSnapshot().getPosition(s, lineNumber-1).beginOfLine();
  1635 			JavaEditorFrame jef = TopLevel.showEditor(s, currentPosition, true);
  1636 
  1637 			if (oldPosition != null)
  1638 				Block.line(oldPosition).redraw();
  1639 
  1640 			Block.line(currentPosition).redraw();
  1641 		}
  1642 		catch (IOException e)
  1643 		{
  1644 			TopLevel.getOutput().show();
  1645 			TopLevel.getOutput().println("class '"+className+"' not found");
  1646 		}
  1647 
  1648 		watches.updateContent();
  1649 		localsView.update(LocalsView.HINT_COMPLETE_UPDATE, -1);
  1650 		callStackView.update(CallStackView.HINT_COMPLETE_UPDATE, -1);
  1651 		threadsView.update(ThreadsView.HINT_COMPLETE_UPDATE, -1);
  1652 		//	threadsView.highlightThread(t);
  1653 	}
  1654 
  1655 	/**
  1656 	 * Returns the current value of the variable specified by the name variableName
  1657 	 * The argument i indexes the current stack frame of the current thread.
  1658 	 */
  1659 	/*	    String getCurrentValue(String variableName, int i)
  1660 	{
  1661 		String returnValue;
  1662 
  1663 		if (currentThread == null)
  1664 			return "is not defined";
  1665 
  1666 		int currentIndex = currentThread.getCurrentFrameIndex();
  1667 
  1668 		currentThread.resetCurrentFrameIndex();
  1669 		currentThread.setCurrentFrameIndex(currentIndex);
  1670 		returnValue = getCurrentValue(variableName);
  1671 		currentThread.setCurrentFrameIndex(currentIndex);
  1672 		currentThread.resetCurrentFrameIndex();
  1673 
  1674 		return returnValue;
  1675 	}*/
  1676 
  1677 	public void currentSnapshotHasChanged(Snapshot oldSnapshot)
  1678 	{
  1679 		int numberOfBreakpoints = breakpoints.getNumberOfBreakpoints();
  1680 
  1681 		for(int i = 0; i < numberOfBreakpoints; i++)
  1682 		{
  1683 			try
  1684 			{
  1685 				Breakpoint breakpoint = breakpoints.getBreakpoint(i);
  1686 
  1687 				Source s = new Source(breakpoint.getClassName());
  1688 				Position position = oldSnapshot.getPosition(s, breakpoint.getLineNumber()-1).beginOfLine();
  1689 				PositionInfo pi = TopLevel.getCurrentSnapshot().getPositionInfo(position);
  1690 
  1691 				breakpoint.setLineNumber(pi.getLine()+1);
  1692 			}
  1693 			catch(Exception e)
  1694 			{
  1695 				//e.printStackTrace();
  1696 			}
  1697 		}
  1698 
  1699 		breakpoints.updateContent();
  1700 	}
  1701 }