001: /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002: *
003: * ***** BEGIN LICENSE BLOCK *****
004: * Version: MPL 1.1/GPL 2.0
005: *
006: * The contents of this file are subject to the Mozilla Public License Version
007: * 1.1 (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: * http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the
014: * License.
015: *
016: * The Original Code is Rhino JavaScript Debugger code, released
017: * November 21, 2000.
018: *
019: * The Initial Developer of the Original Code is
020: * SeeBeyond Corporation.
021: * Portions created by the Initial Developer are Copyright (C) 2000
022: * the Initial Developer. All Rights Reserved.
023: *
024: * Contributor(s):
025: * Igor Bukanov
026: * Matt Gould
027: * Christopher Oliver
028: * Cameron McCormack
029: *
030: * Alternatively, the contents of this file may be used under the terms of
031: * the GNU General Public License Version 2 or later (the "GPL"), in which
032: * case the provisions of the GPL are applicable instead of those above. If
033: * you wish to allow use of your version of this file only under the terms of
034: * the GPL and not to allow others to use your version of this file under the
035: * MPL, indicate your decision by deleting the provisions above and replacing
036: * them with the notice and other provisions required by the GPL. If you do
037: * not delete the provisions above, a recipient may use your version of this
038: * file under either the MPL or the GPL.
039: *
040: * ***** END LICENSE BLOCK ***** */
041:
042: package org.mozilla.javascript.tools.debugger;
043:
044: import java.io.InputStream;
045: import java.io.PrintStream;
046:
047: import javax.swing.JFrame;
048:
049: import org.mozilla.javascript.*;
050: import org.mozilla.javascript.tools.shell.Global;
051:
052: /**
053: * Rhino script debugger main class. This class links together a
054: * debugger object ({@link Dim}) and a debugger GUI object ({@link SwingGui}).
055: */
056: public class Main {
057:
058: /**
059: * The debugger.
060: */
061: private Dim dim;
062:
063: /**
064: * The debugger frame.
065: */
066: private SwingGui debugGui;
067:
068: /**
069: * Creates a new Main.
070: */
071: public Main(String title) {
072: dim = new Dim();
073: debugGui = new SwingGui(dim, title);
074: }
075:
076: /**
077: * Returns the debugger window {@link JFrame}.
078: */
079: public JFrame getDebugFrame() {
080: return debugGui;
081: }
082:
083: /**
084: * Breaks execution of the script.
085: */
086: public void doBreak() {
087: dim.setBreak();
088: }
089:
090: /**
091: * Sets whether execution should break when a script exception is thrown.
092: */
093: public void setBreakOnExceptions(boolean value) {
094: dim.setBreakOnExceptions(value);
095: debugGui.getMenubar().getBreakOnExceptions().setSelected(value);
096: }
097:
098: /**
099: * Sets whether execution should break when a function is entered.
100: */
101: public void setBreakOnEnter(boolean value) {
102: dim.setBreakOnEnter(value);
103: debugGui.getMenubar().getBreakOnEnter().setSelected(value);
104: }
105:
106: /**
107: * Sets whether execution should break when a function is left.
108: */
109: public void setBreakOnReturn(boolean value) {
110: dim.setBreakOnReturn(value);
111: debugGui.getMenubar().getBreakOnReturn().setSelected(value);
112: }
113:
114: /**
115: * Removes all breakpoints.
116: */
117: public void clearAllBreakpoints() {
118: dim.clearAllBreakpoints();
119: }
120:
121: /**
122: * Resumes execution of the script.
123: */
124: public void go() {
125: dim.go();
126: }
127:
128: /**
129: * Sets the scope to be used for script evaluation.
130: */
131: public void setScope(Scriptable scope) {
132: setScopeProvider(IProxy.newScopeProvider(scope));
133: }
134:
135: /**
136: * Sets the {@link ScopeProvider} that provides a scope to be used
137: * for script evaluation.
138: */
139: public void setScopeProvider(ScopeProvider p) {
140: dim.setScopeProvider(p);
141: }
142:
143: /**
144: * Assign a Runnable object that will be invoked when the user
145: * selects "Exit..." or closes the Debugger main window.
146: */
147: public void setExitAction(Runnable r) {
148: debugGui.setExitAction(r);
149: }
150:
151: /**
152: * Returns an {@link InputStream} for stdin from the debugger's internal
153: * Console window.
154: */
155: public InputStream getIn() {
156: return debugGui.getConsole().getIn();
157: }
158:
159: /**
160: * Returns a {@link PrintStream} for stdout to the debugger's internal
161: * Console window.
162: */
163: public PrintStream getOut() {
164: return debugGui.getConsole().getOut();
165: }
166:
167: /**
168: * Returns a {@link PrintStream} for stderr in the Debugger's internal
169: * Console window.
170: */
171: public PrintStream getErr() {
172: return debugGui.getConsole().getErr();
173: }
174:
175: /**
176: * Packs the debugger GUI frame.
177: */
178: public void pack() {
179: debugGui.pack();
180: }
181:
182: /**
183: * Sets the debugger GUI frame dimensions.
184: */
185: public void setSize(int w, int h) {
186: debugGui.setSize(w, h);
187: }
188:
189: /**
190: * Sets the visibility of the debugger GUI frame.
191: */
192: public void setVisible(boolean flag) {
193: debugGui.setVisible(flag);
194: }
195:
196: /**
197: * Returns whether the debugger GUI frame is visible.
198: */
199: public boolean isVisible() {
200: return debugGui.isVisible();
201: }
202:
203: /**
204: * Frees any resources held by the debugger.
205: */
206: public void dispose() {
207: clearAllBreakpoints();
208: dim.go();
209: debugGui.dispose();
210: dim = null;
211: }
212:
213: /**
214: * Attaches the debugger to the given {@link ContextFactory}.
215: */
216: public void attachTo(ContextFactory factory) {
217: dim.attachTo(factory);
218: }
219:
220: /**
221: * Detaches from the current {@link ContextFactory}.
222: */
223: public void detach() {
224: dim.detach();
225: }
226:
227: /**
228: * Main entry point. Creates a debugger attached to a Rhino
229: * {@link org.mozilla.javascript.tools.shell.Main} shell session.
230: */
231: public static void main(String[] args) {
232: Main main = new Main("Rhino JavaScript Debugger");
233: main.doBreak();
234: main.setExitAction(new IProxy(IProxy.EXIT_ACTION));
235:
236: System.setIn(main.getIn());
237: System.setOut(main.getOut());
238: System.setErr(main.getErr());
239:
240: Global global = org.mozilla.javascript.tools.shell.Main
241: .getGlobal();
242: global.setIn(main.getIn());
243: global.setOut(main.getOut());
244: global.setErr(main.getErr());
245:
246: main
247: .attachTo(org.mozilla.javascript.tools.shell.Main.shellContextFactory);
248:
249: main.setScope(global);
250:
251: main.pack();
252: main.setSize(600, 460);
253: main.setVisible(true);
254:
255: org.mozilla.javascript.tools.shell.Main.exec(args);
256: }
257:
258: /**
259: * Entry point for embedded applications. This method attaches
260: * to the global {@link ContextFactory} with a scope of a newly
261: * created {@link Global} object. No I/O redirection is performed
262: * as with {@link #main(String[])}.
263: */
264: public static void mainEmbedded(String title) {
265: ContextFactory factory = ContextFactory.getGlobal();
266: Global global = new Global();
267: global.init(factory);
268: mainEmbedded(factory, global, title);
269: }
270:
271: /**
272: * Entry point for embedded applications. This method attaches
273: * to the given {@link ContextFactory} with the given scope. No
274: * I/O redirection is performed as with {@link #main(String[])}.
275: */
276: public static void mainEmbedded(ContextFactory factory,
277: Scriptable scope, String title) {
278: mainEmbeddedImpl(factory, scope, title);
279: }
280:
281: /**
282: * Entry point for embedded applications. This method attaches
283: * to the given {@link ContextFactory} with the given scope. No
284: * I/O redirection is performed as with {@link #main(String[])}.
285: */
286: public static void mainEmbedded(ContextFactory factory,
287: ScopeProvider scopeProvider, String title) {
288: mainEmbeddedImpl(factory, scopeProvider, title);
289: }
290:
291: /**
292: * Helper method for {@link #mainEmbedded(String)}, etc.
293: */
294: private static void mainEmbeddedImpl(ContextFactory factory,
295: Object scopeProvider, String title) {
296: if (title == null) {
297: title = "Rhino JavaScript Debugger (embedded usage)";
298: }
299: Main main = new Main(title);
300: main.doBreak();
301: main.setExitAction(new IProxy(IProxy.EXIT_ACTION));
302:
303: main.attachTo(factory);
304: if (scopeProvider instanceof ScopeProvider) {
305: main.setScopeProvider((ScopeProvider) scopeProvider);
306: } else {
307: Scriptable scope = (Scriptable) scopeProvider;
308: if (scope instanceof Global) {
309: Global global = (Global) scope;
310: global.setIn(main.getIn());
311: global.setOut(main.getOut());
312: global.setErr(main.getErr());
313: }
314: main.setScope(scope);
315: }
316:
317: main.pack();
318: main.setSize(600, 460);
319: main.setVisible(true);
320: }
321:
322: // Deprecated methods
323:
324: /**
325: * @deprecated Use {@link #setSize(int, int)} instead.
326: */
327: public void setSize(java.awt.Dimension dimension) {
328: debugGui.setSize(dimension.width, dimension.height);
329: }
330:
331: /**
332: * @deprecated
333: * The method does nothing and is only present for compatibility.
334: */
335: public void setOptimizationLevel(int level) {
336: }
337:
338: /**
339: * @deprecated
340: * The method is only present for compatibility and should not be called.
341: */
342: public void contextEntered(Context cx) {
343: throw new IllegalStateException();
344: }
345:
346: /**
347: * @deprecated
348: * The method is only present for compatibility and should not be called.
349: */
350: public void contextExited(Context cx) {
351: throw new IllegalStateException();
352: }
353:
354: /**
355: * @deprecated
356: * The method is only present for compatibility and should not be called.
357: */
358: public void contextCreated(Context cx) {
359: throw new IllegalStateException();
360: }
361:
362: /**
363: * @deprecated
364: * The method is only present for compatibility and should not be called.
365: */
366: public void contextReleased(Context cx) {
367: throw new IllegalStateException();
368: }
369:
370: /**
371: * Class to consolidate all internal implementations of interfaces
372: * to avoid class generation bloat.
373: */
374: private static class IProxy implements Runnable, ScopeProvider {
375:
376: // Constants for 'type'.
377: public static final int EXIT_ACTION = 1;
378: public static final int SCOPE_PROVIDER = 2;
379:
380: /**
381: * The type of interface.
382: */
383: private final int type;
384:
385: /**
386: * The scope object to expose when {@link #type} =
387: * {@link #SCOPE_PROVIDER}.
388: */
389: private Scriptable scope;
390:
391: /**
392: * Creates a new IProxy.
393: */
394: public IProxy(int type) {
395: this .type = type;
396: }
397:
398: /**
399: * Creates a new IProxy that acts as a {@link ScopeProvider}.
400: */
401: public static ScopeProvider newScopeProvider(Scriptable scope) {
402: IProxy scopeProvider = new IProxy(SCOPE_PROVIDER);
403: scopeProvider.scope = scope;
404: return scopeProvider;
405: }
406:
407: // ContextAction
408:
409: /**
410: * Exit action.
411: */
412: public void run() {
413: if (type != EXIT_ACTION)
414: Kit.codeBug();
415: System.exit(0);
416: }
417:
418: // ScopeProvider
419:
420: /**
421: * Returns the scope for script evaluations.
422: */
423: public Scriptable getScope() {
424: if (type != SCOPE_PROVIDER)
425: Kit.codeBug();
426: if (scope == null)
427: Kit.codeBug();
428: return scope;
429: }
430: }
431: }
|