Source Code Cross Referenced for Dim.java in  » Scripting » rhino » org » mozilla » javascript » tools » debugger » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » rhino » org.mozilla.javascript.tools.debugger 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino JavaScript Debugger code, released
0017:         * November 21, 2000.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * SeeBeyond Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Igor Bukanov
0026:         *   Matt Gould
0027:         *   Christopher Oliver
0028:         *   Cameron McCormack
0029:         *
0030:         * Alternatively, the contents of this file may be used under the terms of
0031:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0032:         * case the provisions of the GPL are applicable instead of those above. If
0033:         * you wish to allow use of your version of this file only under the terms of
0034:         * the GPL and not to allow others to use your version of this file under the
0035:         * MPL, indicate your decision by deleting the provisions above and replacing
0036:         * them with the notice and other provisions required by the GPL. If you do
0037:         * not delete the provisions above, a recipient may use your version of this
0038:         * file under either the MPL or the GPL.
0039:         *
0040:         * ***** END LICENSE BLOCK ***** */
0041:        package org.mozilla.javascript.tools.debugger;
0042:
0043:        import org.mozilla.javascript.*;
0044:        import org.mozilla.javascript.debug.*;
0045:        import java.util.*;
0046:        import java.io.*;
0047:        import java.net.URL;
0048:
0049:        /**
0050:         * Dim or Debugger Implementation for Rhino.
0051:         */
0052:        public class Dim {
0053:
0054:            // Constants for instructing the debugger what action to perform
0055:            // to end interruption.  Used by 'returnValue'.
0056:            public static final int STEP_OVER = 0;
0057:            public static final int STEP_INTO = 1;
0058:            public static final int STEP_OUT = 2;
0059:            public static final int GO = 3;
0060:            public static final int BREAK = 4;
0061:            public static final int EXIT = 5;
0062:
0063:            // Constants for the DimIProxy interface implementation class.
0064:            private static final int IPROXY_DEBUG = 0;
0065:            private static final int IPROXY_LISTEN = 1;
0066:            private static final int IPROXY_COMPILE_SCRIPT = 2;
0067:            private static final int IPROXY_EVAL_SCRIPT = 3;
0068:            private static final int IPROXY_STRING_IS_COMPILABLE = 4;
0069:            private static final int IPROXY_OBJECT_TO_STRING = 5;
0070:            private static final int IPROXY_OBJECT_PROPERTY = 6;
0071:            private static final int IPROXY_OBJECT_IDS = 7;
0072:
0073:            /**
0074:             * Interface to the debugger GUI.
0075:             */
0076:            private GuiCallback callback;
0077:
0078:            /**
0079:             * Whether the debugger should break.
0080:             */
0081:            private boolean breakFlag;
0082:
0083:            /**
0084:             * The ScopeProvider object that provides the scope in which to
0085:             * evaluate script.
0086:             */
0087:            private ScopeProvider scopeProvider;
0088:
0089:            /**
0090:             * The index of the current stack frame.
0091:             */
0092:            private int frameIndex = -1;
0093:
0094:            /**
0095:             * Information about the current stack at the point of interruption.
0096:             */
0097:            private volatile ContextData interruptedContextData;
0098:
0099:            /**
0100:             * The ContextFactory to listen to for debugging information.
0101:             */
0102:            private ContextFactory contextFactory;
0103:
0104:            /**
0105:             * Synchronization object used to allow script evaluations to
0106:             * happen when a thread is resumed.
0107:             */
0108:            private Object monitor = new Object();
0109:
0110:            /**
0111:             * Synchronization object used to wait for valid
0112:             * {@link #interruptedContextData}.
0113:             */
0114:            private Object eventThreadMonitor = new Object();
0115:
0116:            /**
0117:             * The action to perform to end the interruption loop.
0118:             */
0119:            private volatile int returnValue = -1;
0120:
0121:            /**
0122:             * Whether the debugger is inside the interruption loop.
0123:             */
0124:            private boolean insideInterruptLoop;
0125:
0126:            /**
0127:             * The requested script string to be evaluated when the thread
0128:             * has been resumed.
0129:             */
0130:            private String evalRequest;
0131:
0132:            /**
0133:             * The stack frame in which to evaluate {@link #evalRequest}.
0134:             */
0135:            private StackFrame evalFrame;
0136:
0137:            /**
0138:             * The result of evaluating {@link #evalRequest}.
0139:             */
0140:            private String evalResult;
0141:
0142:            /**
0143:             * Whether the debugger should break when a script exception is thrown.
0144:             */
0145:            private boolean breakOnExceptions;
0146:
0147:            /**
0148:             * Whether the debugger should break when a script function is entered.
0149:             */
0150:            private boolean breakOnEnter;
0151:
0152:            /**
0153:             * Whether the debugger should break when a script function is returned
0154:             * from.
0155:             */
0156:            private boolean breakOnReturn;
0157:
0158:            /**
0159:             * Table mapping URLs to information about the script source.
0160:             */
0161:            private final Hashtable urlToSourceInfo = new Hashtable();
0162:
0163:            /**
0164:             * Table mapping function names to information about the function.
0165:             */
0166:            private final Hashtable functionNames = new Hashtable();
0167:
0168:            /**
0169:             * Table mapping functions to information about the function.
0170:             */
0171:            private final Hashtable functionToSource = new Hashtable();
0172:
0173:            /**
0174:             * ContextFactory.Listener instance attached to {@link #contextFactory}.
0175:             */
0176:            private DimIProxy listener;
0177:
0178:            /**
0179:             * Sets the GuiCallback object to use.
0180:             */
0181:            public void setGuiCallback(GuiCallback callback) {
0182:                this .callback = callback;
0183:            }
0184:
0185:            /**
0186:             * Tells the debugger to break at the next opportunity.
0187:             */
0188:            public void setBreak() {
0189:                this .breakFlag = true;
0190:            }
0191:
0192:            /**
0193:             * Sets the ScopeProvider to be used.
0194:             */
0195:            public void setScopeProvider(ScopeProvider scopeProvider) {
0196:                this .scopeProvider = scopeProvider;
0197:            }
0198:
0199:            /**
0200:             * Switches context to the stack frame with the given index.
0201:             */
0202:            public void contextSwitch(int frameIndex) {
0203:                this .frameIndex = frameIndex;
0204:            }
0205:
0206:            /**
0207:             * Sets whether the debugger should break on exceptions.
0208:             */
0209:            public void setBreakOnExceptions(boolean breakOnExceptions) {
0210:                this .breakOnExceptions = breakOnExceptions;
0211:            }
0212:
0213:            /**
0214:             * Sets whether the debugger should break on function entering.
0215:             */
0216:            public void setBreakOnEnter(boolean breakOnEnter) {
0217:                this .breakOnEnter = breakOnEnter;
0218:            }
0219:
0220:            /**
0221:             * Sets whether the debugger should break on function return.
0222:             */
0223:            public void setBreakOnReturn(boolean breakOnReturn) {
0224:                this .breakOnReturn = breakOnReturn;
0225:            }
0226:
0227:            /**
0228:             * Attaches the debugger to the given ContextFactory.
0229:             */
0230:            public void attachTo(ContextFactory factory) {
0231:                detach();
0232:                this .contextFactory = factory;
0233:                this .listener = new DimIProxy(this , IPROXY_LISTEN);
0234:                factory.addListener(this .listener);
0235:            }
0236:
0237:            /**
0238:             * Detaches the debugger from the current ContextFactory.
0239:             */
0240:            public void detach() {
0241:                if (listener != null) {
0242:                    contextFactory.removeListener(listener);
0243:                    contextFactory = null;
0244:                    listener = null;
0245:                }
0246:            }
0247:
0248:            /**
0249:             * Releases resources associated with this debugger.
0250:             */
0251:            public void dispose() {
0252:                detach();
0253:            }
0254:
0255:            /**
0256:             * Returns the FunctionSource object for the given script or function.
0257:             */
0258:            private FunctionSource getFunctionSource(DebuggableScript fnOrScript) {
0259:                FunctionSource fsource = functionSource(fnOrScript);
0260:                if (fsource == null) {
0261:                    String url = getNormalizedUrl(fnOrScript);
0262:                    SourceInfo si = sourceInfo(url);
0263:                    if (si == null) {
0264:                        if (!fnOrScript.isGeneratedScript()) {
0265:                            // Not eval or Function, try to load it from URL
0266:                            String source = loadSource(url);
0267:                            if (source != null) {
0268:                                DebuggableScript top = fnOrScript;
0269:                                for (;;) {
0270:                                    DebuggableScript parent = top.getParent();
0271:                                    if (parent == null) {
0272:                                        break;
0273:                                    }
0274:                                    top = parent;
0275:                                }
0276:                                registerTopScript(top, source);
0277:                                fsource = functionSource(fnOrScript);
0278:                            }
0279:                        }
0280:                    }
0281:                }
0282:                return fsource;
0283:            }
0284:
0285:            /**
0286:             * Loads the script at the given URL.
0287:             */
0288:            private String loadSource(String sourceUrl) {
0289:                String source = null;
0290:                int hash = sourceUrl.indexOf('#');
0291:                if (hash >= 0) {
0292:                    sourceUrl = sourceUrl.substring(0, hash);
0293:                }
0294:                try {
0295:                    InputStream is;
0296:                    openStream: {
0297:                        if (sourceUrl.indexOf(':') < 0) {
0298:                            // Can be a file name
0299:                            try {
0300:                                if (sourceUrl.startsWith("~/")) {
0301:                                    String home = SecurityUtilities
0302:                                            .getSystemProperty("user.home");
0303:                                    if (home != null) {
0304:                                        String pathFromHome = sourceUrl
0305:                                                .substring(2);
0306:                                        File f = new File(new File(home),
0307:                                                pathFromHome);
0308:                                        if (f.exists()) {
0309:                                            is = new FileInputStream(f);
0310:                                            break openStream;
0311:                                        }
0312:                                    }
0313:                                }
0314:                                File f = new File(sourceUrl);
0315:                                if (f.exists()) {
0316:                                    is = new FileInputStream(f);
0317:                                    break openStream;
0318:                                }
0319:                            } catch (SecurityException ex) {
0320:                            }
0321:                            // No existing file, assume missed http://
0322:                            if (sourceUrl.startsWith("//")) {
0323:                                sourceUrl = "http:" + sourceUrl;
0324:                            } else if (sourceUrl.startsWith("/")) {
0325:                                sourceUrl = "http://127.0.0.1" + sourceUrl;
0326:                            } else {
0327:                                sourceUrl = "http://" + sourceUrl;
0328:                            }
0329:                        }
0330:
0331:                        is = (new URL(sourceUrl)).openStream();
0332:                    }
0333:
0334:                    try {
0335:                        source = Kit.readReader(new InputStreamReader(is));
0336:                    } finally {
0337:                        is.close();
0338:                    }
0339:                } catch (IOException ex) {
0340:                    System.err.println("Failed to load source from "
0341:                            + sourceUrl + ": " + ex);
0342:                }
0343:                return source;
0344:            }
0345:
0346:            /**
0347:             * Registers the given script as a top-level script in the debugger.
0348:             */
0349:            private void registerTopScript(DebuggableScript topScript,
0350:                    String source) {
0351:                if (!topScript.isTopLevel()) {
0352:                    throw new IllegalArgumentException();
0353:                }
0354:                String url = getNormalizedUrl(topScript);
0355:                DebuggableScript[] functions = getAllFunctions(topScript);
0356:                final SourceInfo sourceInfo = new SourceInfo(source, functions,
0357:                        url);
0358:
0359:                synchronized (urlToSourceInfo) {
0360:                    SourceInfo old = (SourceInfo) urlToSourceInfo.get(url);
0361:                    if (old != null) {
0362:                        sourceInfo.copyBreakpointsFrom(old);
0363:                    }
0364:                    urlToSourceInfo.put(url, sourceInfo);
0365:                    for (int i = 0; i != sourceInfo.functionSourcesTop(); ++i) {
0366:                        FunctionSource fsource = sourceInfo.functionSource(i);
0367:                        String name = fsource.name();
0368:                        if (name.length() != 0) {
0369:                            functionNames.put(name, fsource);
0370:                        }
0371:                    }
0372:                }
0373:
0374:                synchronized (functionToSource) {
0375:                    for (int i = 0; i != functions.length; ++i) {
0376:                        FunctionSource fsource = sourceInfo.functionSource(i);
0377:                        functionToSource.put(functions[i], fsource);
0378:                    }
0379:                }
0380:
0381:                callback.updateSourceText(sourceInfo);
0382:            }
0383:
0384:            /**
0385:             * Returns the FunctionSource object for the given function or script.
0386:             */
0387:            private FunctionSource functionSource(DebuggableScript fnOrScript) {
0388:                return (FunctionSource) functionToSource.get(fnOrScript);
0389:            }
0390:
0391:            /**
0392:             * Returns an array of all function names.
0393:             */
0394:            public String[] functionNames() {
0395:                String[] a;
0396:                synchronized (urlToSourceInfo) {
0397:                    Enumeration e = functionNames.keys();
0398:                    a = new String[functionNames.size()];
0399:                    int i = 0;
0400:                    while (e.hasMoreElements()) {
0401:                        a[i++] = (String) e.nextElement();
0402:                    }
0403:                }
0404:                return a;
0405:            }
0406:
0407:            /**
0408:             * Returns the FunctionSource object for the function with the given name.
0409:             */
0410:            public FunctionSource functionSourceByName(String functionName) {
0411:                return (FunctionSource) functionNames.get(functionName);
0412:            }
0413:
0414:            /**
0415:             * Returns the SourceInfo object for the given URL.
0416:             */
0417:            public SourceInfo sourceInfo(String url) {
0418:                return (SourceInfo) urlToSourceInfo.get(url);
0419:            }
0420:
0421:            /**
0422:             * Returns the source URL for the given script or function.
0423:             */
0424:            private String getNormalizedUrl(DebuggableScript fnOrScript) {
0425:                String url = fnOrScript.getSourceName();
0426:                if (url == null) {
0427:                    url = "<stdin>";
0428:                } else {
0429:                    // Not to produce window for eval from different lines,
0430:                    // strip line numbers, i.e. replace all #[0-9]+\(eval\) by
0431:                    // (eval)
0432:                    // Option: similar teatment for Function?
0433:                    char evalSeparator = '#';
0434:                    StringBuffer sb = null;
0435:                    int urlLength = url.length();
0436:                    int cursor = 0;
0437:                    for (;;) {
0438:                        int searchStart = url.indexOf(evalSeparator, cursor);
0439:                        if (searchStart < 0) {
0440:                            break;
0441:                        }
0442:                        String replace = null;
0443:                        int i = searchStart + 1;
0444:                        while (i != urlLength) {
0445:                            int c = url.charAt(i);
0446:                            if (!('0' <= c && c <= '9')) {
0447:                                break;
0448:                            }
0449:                            ++i;
0450:                        }
0451:                        if (i != searchStart + 1) {
0452:                            // i points after #[0-9]+
0453:                            if ("(eval)".regionMatches(0, url, i, 6)) {
0454:                                cursor = i + 6;
0455:                                replace = "(eval)";
0456:                            }
0457:                        }
0458:                        if (replace == null) {
0459:                            break;
0460:                        }
0461:                        if (sb == null) {
0462:                            sb = new StringBuffer();
0463:                            sb.append(url.substring(0, searchStart));
0464:                        }
0465:                        sb.append(replace);
0466:                    }
0467:                    if (sb != null) {
0468:                        if (cursor != urlLength) {
0469:                            sb.append(url.substring(cursor));
0470:                        }
0471:                        url = sb.toString();
0472:                    }
0473:                }
0474:                return url;
0475:            }
0476:
0477:            /**
0478:             * Returns an array of all functions in the given script.
0479:             */
0480:            private static DebuggableScript[] getAllFunctions(
0481:                    DebuggableScript function) {
0482:                ObjArray functions = new ObjArray();
0483:                collectFunctions_r(function, functions);
0484:                DebuggableScript[] result = new DebuggableScript[functions
0485:                        .size()];
0486:                functions.toArray(result);
0487:                return result;
0488:            }
0489:
0490:            /**
0491:             * Helper function for {@link #getAllFunctions(DebuggableScript)}.
0492:             */
0493:            private static void collectFunctions_r(DebuggableScript function,
0494:                    ObjArray array) {
0495:                array.add(function);
0496:                for (int i = 0; i != function.getFunctionCount(); ++i) {
0497:                    collectFunctions_r(function.getFunction(i), array);
0498:                }
0499:            }
0500:
0501:            /**
0502:             * Clears all breakpoints.
0503:             */
0504:            public void clearAllBreakpoints() {
0505:                Enumeration e = urlToSourceInfo.elements();
0506:                while (e.hasMoreElements()) {
0507:                    SourceInfo si = (SourceInfo) e.nextElement();
0508:                    si.removeAllBreakpoints();
0509:                }
0510:            }
0511:
0512:            /**
0513:             * Called when a breakpoint has been hit.
0514:             */
0515:            private void handleBreakpointHit(StackFrame frame, Context cx) {
0516:                breakFlag = false;
0517:                interrupted(cx, frame, null);
0518:            }
0519:
0520:            /**
0521:             * Called when a script exception has been thrown.
0522:             */
0523:            private void handleExceptionThrown(Context cx, Throwable ex,
0524:                    StackFrame frame) {
0525:                if (breakOnExceptions) {
0526:                    ContextData cd = frame.contextData();
0527:                    if (cd.lastProcessedException != ex) {
0528:                        interrupted(cx, frame, ex);
0529:                        cd.lastProcessedException = ex;
0530:                    }
0531:                }
0532:            }
0533:
0534:            /**
0535:             * Returns the current ContextData object.
0536:             */
0537:            public ContextData currentContextData() {
0538:                return interruptedContextData;
0539:            }
0540:
0541:            /**
0542:             * Sets the action to perform to end interruption.
0543:             */
0544:            public void setReturnValue(int returnValue) {
0545:                synchronized (monitor) {
0546:                    this .returnValue = returnValue;
0547:                    monitor.notify();
0548:                }
0549:            }
0550:
0551:            /**
0552:             * Resumes execution of script.
0553:             */
0554:            public void go() {
0555:                synchronized (monitor) {
0556:                    this .returnValue = GO;
0557:                    monitor.notifyAll();
0558:                }
0559:            }
0560:
0561:            /**
0562:             * Evaluates the given script.
0563:             */
0564:            public String eval(String expr) {
0565:                String result = "undefined";
0566:                if (expr == null) {
0567:                    return result;
0568:                }
0569:                ContextData contextData = currentContextData();
0570:                if (contextData == null
0571:                        || frameIndex >= contextData.frameCount()) {
0572:                    return result;
0573:                }
0574:                StackFrame frame = contextData.getFrame(frameIndex);
0575:                if (contextData.eventThreadFlag) {
0576:                    Context cx = Context.getCurrentContext();
0577:                    result = do_eval(cx, frame, expr);
0578:                } else {
0579:                    synchronized (monitor) {
0580:                        if (insideInterruptLoop) {
0581:                            evalRequest = expr;
0582:                            evalFrame = frame;
0583:                            monitor.notify();
0584:                            do {
0585:                                try {
0586:                                    monitor.wait();
0587:                                } catch (InterruptedException exc) {
0588:                                    Thread.currentThread().interrupt();
0589:                                    break;
0590:                                }
0591:                            } while (evalRequest != null);
0592:                            result = evalResult;
0593:                        }
0594:                    }
0595:                }
0596:                return result;
0597:            }
0598:
0599:            /**
0600:             * Compiles the given script.
0601:             */
0602:            public void compileScript(String url, String text) {
0603:                DimIProxy action = new DimIProxy(this , IPROXY_COMPILE_SCRIPT);
0604:                action.url = url;
0605:                action.text = text;
0606:                action.withContext();
0607:            }
0608:
0609:            /**
0610:             * Evaluates the given script.
0611:             */
0612:            public void evalScript(final String url, final String text) {
0613:                DimIProxy action = new DimIProxy(this , IPROXY_EVAL_SCRIPT);
0614:                action.url = url;
0615:                action.text = text;
0616:                action.withContext();
0617:            }
0618:
0619:            /**
0620:             * Converts the given script object to a string.
0621:             */
0622:            public String objectToString(Object object) {
0623:                DimIProxy action = new DimIProxy(this , IPROXY_OBJECT_TO_STRING);
0624:                action.object = object;
0625:                action.withContext();
0626:                return action.stringResult;
0627:            }
0628:
0629:            /**
0630:             * Returns whether the given string is syntactically valid script.
0631:             */
0632:            public boolean stringIsCompilableUnit(String str) {
0633:                DimIProxy action = new DimIProxy(this ,
0634:                        IPROXY_STRING_IS_COMPILABLE);
0635:                action.text = str;
0636:                action.withContext();
0637:                return action.booleanResult;
0638:            }
0639:
0640:            /**
0641:             * Returns the value of a property on the given script object.
0642:             */
0643:            public Object getObjectProperty(Object object, Object id) {
0644:                DimIProxy action = new DimIProxy(this , IPROXY_OBJECT_PROPERTY);
0645:                action.object = object;
0646:                action.id = id;
0647:                action.withContext();
0648:                return action.objectResult;
0649:            }
0650:
0651:            /**
0652:             * Returns an array of the property names on the given script object.
0653:             */
0654:            public Object[] getObjectIds(Object object) {
0655:                DimIProxy action = new DimIProxy(this , IPROXY_OBJECT_IDS);
0656:                action.object = object;
0657:                action.withContext();
0658:                return action.objectArrayResult;
0659:            }
0660:
0661:            /**
0662:             * Returns the value of a property on the given script object.
0663:             */
0664:            private Object getObjectPropertyImpl(Context cx, Object object,
0665:                    Object id) {
0666:                Scriptable scriptable = (Scriptable) object;
0667:                Object result;
0668:                if (id instanceof  String) {
0669:                    String name = (String) id;
0670:                    if (name.equals("this")) {
0671:                        result = scriptable;
0672:                    } else if (name.equals("__proto__")) {
0673:                        result = scriptable.getPrototype();
0674:                    } else if (name.equals("__parent__")) {
0675:                        result = scriptable.getParentScope();
0676:                    } else {
0677:                        result = ScriptableObject.getProperty(scriptable, name);
0678:                        if (result == ScriptableObject.NOT_FOUND) {
0679:                            result = Undefined.instance;
0680:                        }
0681:                    }
0682:                } else {
0683:                    int index = ((Integer) id).intValue();
0684:                    result = ScriptableObject.getProperty(scriptable, index);
0685:                    if (result == ScriptableObject.NOT_FOUND) {
0686:                        result = Undefined.instance;
0687:                    }
0688:                }
0689:                return result;
0690:            }
0691:
0692:            /**
0693:             * Returns an array of the property names on the given script object.
0694:             */
0695:            private Object[] getObjectIdsImpl(Context cx, Object object) {
0696:                if (!(object instanceof  Scriptable)
0697:                        || object == Undefined.instance) {
0698:                    return Context.emptyArgs;
0699:                }
0700:
0701:                Object[] ids;
0702:                Scriptable scriptable = (Scriptable) object;
0703:                if (scriptable instanceof  DebuggableObject) {
0704:                    ids = ((DebuggableObject) scriptable).getAllIds();
0705:                } else {
0706:                    ids = scriptable.getIds();
0707:                }
0708:
0709:                Scriptable proto = scriptable.getPrototype();
0710:                Scriptable parent = scriptable.getParentScope();
0711:                int extra = 0;
0712:                if (proto != null) {
0713:                    ++extra;
0714:                }
0715:                if (parent != null) {
0716:                    ++extra;
0717:                }
0718:                if (extra != 0) {
0719:                    Object[] tmp = new Object[extra + ids.length];
0720:                    System.arraycopy(ids, 0, tmp, extra, ids.length);
0721:                    ids = tmp;
0722:                    extra = 0;
0723:                    if (proto != null) {
0724:                        ids[extra++] = "__proto__";
0725:                    }
0726:                    if (parent != null) {
0727:                        ids[extra++] = "__parent__";
0728:                    }
0729:                }
0730:
0731:                return ids;
0732:            }
0733:
0734:            /**
0735:             * Interrupts script execution.
0736:             */
0737:            private void interrupted(Context cx, final StackFrame frame,
0738:                    Throwable scriptException) {
0739:                ContextData contextData = frame.contextData();
0740:                boolean eventThreadFlag = callback.isGuiEventThread();
0741:                contextData.eventThreadFlag = eventThreadFlag;
0742:
0743:                boolean recursiveEventThreadCall = false;
0744:
0745:                interruptedCheck: synchronized (eventThreadMonitor) {
0746:                    if (eventThreadFlag) {
0747:                        if (interruptedContextData != null) {
0748:                            recursiveEventThreadCall = true;
0749:                            break interruptedCheck;
0750:                        }
0751:                    } else {
0752:                        while (interruptedContextData != null) {
0753:                            try {
0754:                                eventThreadMonitor.wait();
0755:                            } catch (InterruptedException exc) {
0756:                                return;
0757:                            }
0758:                        }
0759:                    }
0760:                    interruptedContextData = contextData;
0761:                }
0762:
0763:                if (recursiveEventThreadCall) {
0764:                    // XXX: For now the following is commented out as on Linux
0765:                    // too deep recursion of dispatchNextGuiEvent causes GUI lockout.
0766:                    // Note: it can make GUI unresponsive if long-running script
0767:                    // will be called on GUI thread while processing another interrupt
0768:                    if (false) {
0769:                        // Run event dispatch until gui sets a flag to exit the initial
0770:                        // call to interrupted.
0771:                        while (this .returnValue == -1) {
0772:                            try {
0773:                                callback.dispatchNextGuiEvent();
0774:                            } catch (InterruptedException exc) {
0775:                            }
0776:                        }
0777:                    }
0778:                    return;
0779:                }
0780:
0781:                if (interruptedContextData == null)
0782:                    Kit.codeBug();
0783:
0784:                try {
0785:                    do {
0786:                        int frameCount = contextData.frameCount();
0787:                        this .frameIndex = frameCount - 1;
0788:
0789:                        final String threadTitle = Thread.currentThread()
0790:                                .toString();
0791:                        final String alertMessage;
0792:                        if (scriptException == null) {
0793:                            alertMessage = null;
0794:                        } else {
0795:                            alertMessage = scriptException.toString();
0796:                        }
0797:
0798:                        int returnValue = -1;
0799:                        if (!eventThreadFlag) {
0800:                            synchronized (monitor) {
0801:                                if (insideInterruptLoop)
0802:                                    Kit.codeBug();
0803:                                this .insideInterruptLoop = true;
0804:                                this .evalRequest = null;
0805:                                this .returnValue = -1;
0806:                                callback.enterInterrupt(frame, threadTitle,
0807:                                        alertMessage);
0808:                                try {
0809:                                    for (;;) {
0810:                                        try {
0811:                                            monitor.wait();
0812:                                        } catch (InterruptedException exc) {
0813:                                            Thread.currentThread().interrupt();
0814:                                            break;
0815:                                        }
0816:                                        if (evalRequest != null) {
0817:                                            this .evalResult = null;
0818:                                            try {
0819:                                                evalResult = do_eval(cx,
0820:                                                        evalFrame, evalRequest);
0821:                                            } finally {
0822:                                                evalRequest = null;
0823:                                                evalFrame = null;
0824:                                                monitor.notify();
0825:                                            }
0826:                                            continue;
0827:                                        }
0828:                                        if (this .returnValue != -1) {
0829:                                            returnValue = this .returnValue;
0830:                                            break;
0831:                                        }
0832:                                    }
0833:                                } finally {
0834:                                    insideInterruptLoop = false;
0835:                                }
0836:                            }
0837:                        } else {
0838:                            this .returnValue = -1;
0839:                            callback.enterInterrupt(frame, threadTitle,
0840:                                    alertMessage);
0841:                            while (this .returnValue == -1) {
0842:                                try {
0843:                                    callback.dispatchNextGuiEvent();
0844:                                } catch (InterruptedException exc) {
0845:                                }
0846:                            }
0847:                            returnValue = this .returnValue;
0848:                        }
0849:                        switch (returnValue) {
0850:                        case STEP_OVER:
0851:                            contextData.breakNextLine = true;
0852:                            contextData.stopAtFrameDepth = contextData
0853:                                    .frameCount();
0854:                            break;
0855:                        case STEP_INTO:
0856:                            contextData.breakNextLine = true;
0857:                            contextData.stopAtFrameDepth = -1;
0858:                            break;
0859:                        case STEP_OUT:
0860:                            if (contextData.frameCount() > 1) {
0861:                                contextData.breakNextLine = true;
0862:                                contextData.stopAtFrameDepth = contextData
0863:                                        .frameCount() - 1;
0864:                            }
0865:                            break;
0866:                        }
0867:                    } while (false);
0868:                } finally {
0869:                    synchronized (eventThreadMonitor) {
0870:                        interruptedContextData = null;
0871:                        eventThreadMonitor.notifyAll();
0872:                    }
0873:                }
0874:
0875:            }
0876:
0877:            /**
0878:             * Evaluates script in the given stack frame.
0879:             */
0880:            private static String do_eval(Context cx, StackFrame frame,
0881:                    String expr) {
0882:                String resultString;
0883:                Debugger saved_debugger = cx.getDebugger();
0884:                Object saved_data = cx.getDebuggerContextData();
0885:                int saved_level = cx.getOptimizationLevel();
0886:
0887:                cx.setDebugger(null, null);
0888:                cx.setOptimizationLevel(-1);
0889:                cx.setGeneratingDebug(false);
0890:                try {
0891:                    Callable script = (Callable) cx.compileString(expr, "", 0,
0892:                            null);
0893:                    Object result = script.call(cx, frame.scope, frame.this Obj,
0894:                            ScriptRuntime.emptyArgs);
0895:                    if (result == Undefined.instance) {
0896:                        resultString = "";
0897:                    } else {
0898:                        resultString = ScriptRuntime.toString(result);
0899:                    }
0900:                } catch (Exception exc) {
0901:                    resultString = exc.getMessage();
0902:                } finally {
0903:                    cx.setGeneratingDebug(true);
0904:                    cx.setOptimizationLevel(saved_level);
0905:                    cx.setDebugger(saved_debugger, saved_data);
0906:                }
0907:                if (resultString == null) {
0908:                    resultString = "null";
0909:                }
0910:                return resultString;
0911:            }
0912:
0913:            /**
0914:             * Proxy class to implement debug interfaces without bloat of class
0915:             * files.
0916:             */
0917:            private static class DimIProxy implements  ContextAction,
0918:                    ContextFactory.Listener, Debugger {
0919:
0920:                /**
0921:                 * The debugger.
0922:                 */
0923:                private Dim dim;
0924:
0925:                /**
0926:                 * The interface implementation type.  One of the IPROXY_* constants
0927:                 * defined in {@link Dim}.
0928:                 */
0929:                private int type;
0930:
0931:                /**
0932:                 * The URL origin of the script to compile or evaluate.
0933:                 */
0934:                private String url;
0935:
0936:                /**
0937:                 * The text of the script to compile, evaluate or test for compilation.
0938:                 */
0939:                private String text;
0940:
0941:                /**
0942:                 * The object to convert, get a property from or enumerate.
0943:                 */
0944:                private Object object;
0945:
0946:                /**
0947:                 * The property to look up in {@link #object}.
0948:                 */
0949:                private Object id;
0950:
0951:                /**
0952:                 * The boolean result of the action.
0953:                 */
0954:                private boolean booleanResult;
0955:
0956:                /**
0957:                 * The String result of the action.
0958:                 */
0959:                private String stringResult;
0960:
0961:                /**
0962:                 * The Object result of the action.
0963:                 */
0964:                private Object objectResult;
0965:
0966:                /**
0967:                 * The Object[] result of the action.
0968:                 */
0969:                private Object[] objectArrayResult;
0970:
0971:                /**
0972:                 * Creates a new DimIProxy.
0973:                 */
0974:                private DimIProxy(Dim dim, int type) {
0975:                    this .dim = dim;
0976:                    this .type = type;
0977:                }
0978:
0979:                // ContextAction
0980:
0981:                /**
0982:                 * Performs the action given by {@link #type}.
0983:                 */
0984:                public Object run(Context cx) {
0985:                    switch (type) {
0986:                    case IPROXY_COMPILE_SCRIPT:
0987:                        cx.compileString(text, url, 1, null);
0988:                        break;
0989:
0990:                    case IPROXY_EVAL_SCRIPT: {
0991:                        Scriptable scope = null;
0992:                        if (dim.scopeProvider != null) {
0993:                            scope = dim.scopeProvider.getScope();
0994:                        }
0995:                        if (scope == null) {
0996:                            scope = new ImporterTopLevel(cx);
0997:                        }
0998:                        cx.evaluateString(scope, text, url, 1, null);
0999:                    }
1000:                        break;
1001:
1002:                    case IPROXY_STRING_IS_COMPILABLE:
1003:                        booleanResult = cx.stringIsCompilableUnit(text);
1004:                        break;
1005:
1006:                    case IPROXY_OBJECT_TO_STRING:
1007:                        if (object == Undefined.instance) {
1008:                            stringResult = "undefined";
1009:                        } else if (object == null) {
1010:                            stringResult = "null";
1011:                        } else if (object instanceof  NativeCall) {
1012:                            stringResult = "[object Call]";
1013:                        } else {
1014:                            stringResult = Context.toString(object);
1015:                        }
1016:                        break;
1017:
1018:                    case IPROXY_OBJECT_PROPERTY:
1019:                        objectResult = dim
1020:                                .getObjectPropertyImpl(cx, object, id);
1021:                        break;
1022:
1023:                    case IPROXY_OBJECT_IDS:
1024:                        objectArrayResult = dim.getObjectIdsImpl(cx, object);
1025:                        break;
1026:
1027:                    default:
1028:                        throw Kit.codeBug();
1029:                    }
1030:                    return null;
1031:                }
1032:
1033:                /**
1034:                 * Performs the action given by {@link #type} with the attached
1035:                 * {@link ContextFactory}.
1036:                 */
1037:                private void withContext() {
1038:                    dim.contextFactory.call(this );
1039:                }
1040:
1041:                // ContextFactory.Listener
1042:
1043:                /**
1044:                 * Called when a Context is created.
1045:                 */
1046:                public void contextCreated(Context cx) {
1047:                    if (type != IPROXY_LISTEN)
1048:                        Kit.codeBug();
1049:                    ContextData contextData = new ContextData();
1050:                    Debugger debugger = new DimIProxy(dim, IPROXY_DEBUG);
1051:                    cx.setDebugger(debugger, contextData);
1052:                    cx.setGeneratingDebug(true);
1053:                    cx.setOptimizationLevel(-1);
1054:                }
1055:
1056:                /**
1057:                 * Called when a Context is destroyed.
1058:                 */
1059:                public void contextReleased(Context cx) {
1060:                    if (type != IPROXY_LISTEN)
1061:                        Kit.codeBug();
1062:                }
1063:
1064:                // Debugger
1065:
1066:                /**
1067:                 * Returns a StackFrame for the given function or script.
1068:                 */
1069:                public DebugFrame getFrame(Context cx,
1070:                        DebuggableScript fnOrScript) {
1071:                    if (type != IPROXY_DEBUG)
1072:                        Kit.codeBug();
1073:
1074:                    FunctionSource item = dim.getFunctionSource(fnOrScript);
1075:                    if (item == null) {
1076:                        // Can not debug if source is not available
1077:                        return null;
1078:                    }
1079:                    return new StackFrame(cx, dim, item);
1080:                }
1081:
1082:                /**
1083:                 * Called when compilation is finished.
1084:                 */
1085:                public void handleCompilationDone(Context cx,
1086:                        DebuggableScript fnOrScript, String source) {
1087:                    if (type != IPROXY_DEBUG)
1088:                        Kit.codeBug();
1089:
1090:                    if (!fnOrScript.isTopLevel()) {
1091:                        return;
1092:                    }
1093:                    dim.registerTopScript(fnOrScript, source);
1094:                }
1095:            }
1096:
1097:            /**
1098:             * Class to store information about a stack.
1099:             */
1100:            public static class ContextData {
1101:
1102:                /**
1103:                 * The stack frames.
1104:                 */
1105:                private ObjArray frameStack = new ObjArray();
1106:
1107:                /**
1108:                 * Whether the debugger should break at the next line in this context.
1109:                 */
1110:                private boolean breakNextLine;
1111:
1112:                /**
1113:                 * The frame depth the debugger should stop at.  Used to implement
1114:                 * "step over" and "step out".
1115:                 */
1116:                private int stopAtFrameDepth = -1;
1117:
1118:                /**
1119:                 * Whether this context is in the event thread.
1120:                 */
1121:                private boolean eventThreadFlag;
1122:
1123:                /**
1124:                 * The last exception that was processed.
1125:                 */
1126:                private Throwable lastProcessedException;
1127:
1128:                /**
1129:                 * Returns the ContextData for the given Context.
1130:                 */
1131:                public static ContextData get(Context cx) {
1132:                    return (ContextData) cx.getDebuggerContextData();
1133:                }
1134:
1135:                /**
1136:                 * Returns the number of stack frames.
1137:                 */
1138:                public int frameCount() {
1139:                    return frameStack.size();
1140:                }
1141:
1142:                /**
1143:                 * Returns the stack frame with the given index.
1144:                 */
1145:                public StackFrame getFrame(int frameNumber) {
1146:                    int num = frameStack.size() - frameNumber - 1;
1147:                    return (StackFrame) frameStack.get(num);
1148:                }
1149:
1150:                /**
1151:                 * Pushes a stack frame on to the stack.
1152:                 */
1153:                private void pushFrame(StackFrame frame) {
1154:                    frameStack.push(frame);
1155:                }
1156:
1157:                /**
1158:                 * Pops a stack frame from the stack.
1159:                 */
1160:                private void popFrame() {
1161:                    frameStack.pop();
1162:                }
1163:            }
1164:
1165:            /**
1166:             * Object to represent one stack frame.
1167:             */
1168:            public static class StackFrame implements  DebugFrame {
1169:
1170:                /**
1171:                 * The debugger.
1172:                 */
1173:                private Dim dim;
1174:
1175:                /**
1176:                 * The ContextData for the Context being debugged.
1177:                 */
1178:                private ContextData contextData;
1179:
1180:                /**
1181:                 * The scope.
1182:                 */
1183:                private Scriptable scope;
1184:
1185:                /**
1186:                 * The 'this' object.
1187:                 */
1188:                private Scriptable this Obj;
1189:
1190:                /**
1191:                 * Information about the function.
1192:                 */
1193:                private FunctionSource fsource;
1194:
1195:                /**
1196:                 * Array of breakpoint state for each source line.
1197:                 */
1198:                private boolean[] breakpoints;
1199:
1200:                /**
1201:                 * Current line number.
1202:                 */
1203:                private int lineNumber;
1204:
1205:                /**
1206:                 * Creates a new StackFrame.
1207:                 */
1208:                private StackFrame(Context cx, Dim dim, FunctionSource fsource) {
1209:                    this .dim = dim;
1210:                    this .contextData = ContextData.get(cx);
1211:                    this .fsource = fsource;
1212:                    this .breakpoints = fsource.sourceInfo().breakpoints;
1213:                    this .lineNumber = fsource.firstLine();
1214:                }
1215:
1216:                /**
1217:                 * Called when the stack frame is entered.
1218:                 */
1219:                public void onEnter(Context cx, Scriptable scope,
1220:                        Scriptable this Obj, Object[] args) {
1221:                    contextData.pushFrame(this );
1222:                    this .scope = scope;
1223:                    this .this Obj = this Obj;
1224:                    if (dim.breakOnEnter) {
1225:                        dim.handleBreakpointHit(this , cx);
1226:                    }
1227:                }
1228:
1229:                /**
1230:                 * Called when the current position has changed.
1231:                 */
1232:                public void onLineChange(Context cx, int lineno) {
1233:                    this .lineNumber = lineno;
1234:
1235:                    if (!breakpoints[lineno] && !dim.breakFlag) {
1236:                        boolean lineBreak = contextData.breakNextLine;
1237:                        if (lineBreak && contextData.stopAtFrameDepth >= 0) {
1238:                            lineBreak = (contextData.frameCount() <= contextData.stopAtFrameDepth);
1239:                        }
1240:                        if (!lineBreak) {
1241:                            return;
1242:                        }
1243:                        contextData.stopAtFrameDepth = -1;
1244:                        contextData.breakNextLine = false;
1245:                    }
1246:
1247:                    dim.handleBreakpointHit(this , cx);
1248:                }
1249:
1250:                /**
1251:                 * Called when an exception has been thrown.
1252:                 */
1253:                public void onExceptionThrown(Context cx, Throwable exception) {
1254:                    dim.handleExceptionThrown(cx, exception, this );
1255:                }
1256:
1257:                /**
1258:                 * Called when the stack frame has been left.
1259:                 */
1260:                public void onExit(Context cx, boolean byThrow,
1261:                        Object resultOrException) {
1262:                    if (dim.breakOnReturn && !byThrow) {
1263:                        dim.handleBreakpointHit(this , cx);
1264:                    }
1265:                    contextData.popFrame();
1266:                }
1267:
1268:                /**
1269:                 * Called when a 'debugger' statement is executed.
1270:                 */
1271:                public void onDebuggerStatement(Context cx) {
1272:                    dim.handleBreakpointHit(this , cx);
1273:                }
1274:
1275:                /**
1276:                 * Returns the SourceInfo object for the function.
1277:                 */
1278:                public SourceInfo sourceInfo() {
1279:                    return fsource.sourceInfo();
1280:                }
1281:
1282:                /**
1283:                 * Returns the ContextData object for the Context.
1284:                 */
1285:                public ContextData contextData() {
1286:                    return contextData;
1287:                }
1288:
1289:                /**
1290:                 * Returns the scope object for this frame.
1291:                 */
1292:                public Object scope() {
1293:                    return scope;
1294:                }
1295:
1296:                /**
1297:                 * Returns the 'this' object for this frame.
1298:                 */
1299:                public Object this Obj() {
1300:                    return this Obj;
1301:                }
1302:
1303:                /**
1304:                 * Returns the source URL.
1305:                 */
1306:                public String getUrl() {
1307:                    return fsource.sourceInfo().url();
1308:                }
1309:
1310:                /**
1311:                 * Returns the current line number.
1312:                 */
1313:                public int getLineNumber() {
1314:                    return lineNumber;
1315:                }
1316:            }
1317:
1318:            /**
1319:             * Class to store information about a function.
1320:             */
1321:            public static class FunctionSource {
1322:
1323:                /**
1324:                 * Information about the source of the function.
1325:                 */
1326:                private SourceInfo sourceInfo;
1327:
1328:                /**
1329:                 * Line number of the first line of the function.
1330:                 */
1331:                private int firstLine;
1332:
1333:                /**
1334:                 * The function name.
1335:                 */
1336:                private String name;
1337:
1338:                /**
1339:                 * Creates a new FunctionSource.
1340:                 */
1341:                private FunctionSource(SourceInfo sourceInfo, int firstLine,
1342:                        String name) {
1343:                    if (name == null)
1344:                        throw new IllegalArgumentException();
1345:                    this .sourceInfo = sourceInfo;
1346:                    this .firstLine = firstLine;
1347:                    this .name = name;
1348:                }
1349:
1350:                /**
1351:                 * Returns the SourceInfo object that describes the source of the
1352:                 * function.
1353:                 */
1354:                public SourceInfo sourceInfo() {
1355:                    return sourceInfo;
1356:                }
1357:
1358:                /**
1359:                 * Returns the line number of the first line of the function.
1360:                 */
1361:                public int firstLine() {
1362:                    return firstLine;
1363:                }
1364:
1365:                /**
1366:                 * Returns the name of the function.
1367:                 */
1368:                public String name() {
1369:                    return name;
1370:                }
1371:            }
1372:
1373:            /**
1374:             * Class to store information about a script source.
1375:             */
1376:            public static class SourceInfo {
1377:
1378:                /**
1379:                 * An empty array of booleans.
1380:                 */
1381:                private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
1382:
1383:                /**
1384:                 * The script.
1385:                 */
1386:                private String source;
1387:
1388:                /**
1389:                 * The URL of the script.
1390:                 */
1391:                private String url;
1392:
1393:                /**
1394:                 * Array indicating which lines can have breakpoints set.
1395:                 */
1396:                private boolean[] breakableLines;
1397:
1398:                /**
1399:                 * Array indicating whether a breakpoint is set on the line.
1400:                 */
1401:                private boolean[] breakpoints;
1402:
1403:                /**
1404:                 * Array of FunctionSource objects for the functions in the script.
1405:                 */
1406:                private FunctionSource[] functionSources;
1407:
1408:                /**
1409:                 * Creates a new SourceInfo object.
1410:                 */
1411:                private SourceInfo(String source, DebuggableScript[] functions,
1412:                        String normilizedUrl) {
1413:                    this .source = source;
1414:                    this .url = normilizedUrl;
1415:
1416:                    int N = functions.length;
1417:                    int[][] lineArrays = new int[N][];
1418:                    for (int i = 0; i != N; ++i) {
1419:                        lineArrays[i] = functions[i].getLineNumbers();
1420:                    }
1421:
1422:                    int minAll = 0, maxAll = -1;
1423:                    int[] firstLines = new int[N];
1424:                    for (int i = 0; i != N; ++i) {
1425:                        int[] lines = lineArrays[i];
1426:                        if (lines == null || lines.length == 0) {
1427:                            firstLines[i] = -1;
1428:                        } else {
1429:                            int min, max;
1430:                            min = max = lines[0];
1431:                            for (int j = 1; j != lines.length; ++j) {
1432:                                int line = lines[j];
1433:                                if (line < min) {
1434:                                    min = line;
1435:                                } else if (line > max) {
1436:                                    max = line;
1437:                                }
1438:                            }
1439:                            firstLines[i] = min;
1440:                            if (minAll > maxAll) {
1441:                                minAll = min;
1442:                                maxAll = max;
1443:                            } else {
1444:                                if (min < minAll) {
1445:                                    minAll = min;
1446:                                }
1447:                                if (max > maxAll) {
1448:                                    maxAll = max;
1449:                                }
1450:                            }
1451:                        }
1452:                    }
1453:
1454:                    if (minAll > maxAll) {
1455:                        // No line information
1456:                        this .breakableLines = EMPTY_BOOLEAN_ARRAY;
1457:                        this .breakpoints = EMPTY_BOOLEAN_ARRAY;
1458:                    } else {
1459:                        if (minAll < 0) {
1460:                            // Line numbers can not be negative
1461:                            throw new IllegalStateException(String
1462:                                    .valueOf(minAll));
1463:                        }
1464:                        int linesTop = maxAll + 1;
1465:                        this .breakableLines = new boolean[linesTop];
1466:                        this .breakpoints = new boolean[linesTop];
1467:                        for (int i = 0; i != N; ++i) {
1468:                            int[] lines = lineArrays[i];
1469:                            if (lines != null && lines.length != 0) {
1470:                                for (int j = 0; j != lines.length; ++j) {
1471:                                    int line = lines[j];
1472:                                    this .breakableLines[line] = true;
1473:                                }
1474:                            }
1475:                        }
1476:                    }
1477:                    this .functionSources = new FunctionSource[N];
1478:                    for (int i = 0; i != N; ++i) {
1479:                        String name = functions[i].getFunctionName();
1480:                        if (name == null) {
1481:                            name = "";
1482:                        }
1483:                        this .functionSources[i] = new FunctionSource(this ,
1484:                                firstLines[i], name);
1485:                    }
1486:                }
1487:
1488:                /**
1489:                 * Returns the source text.
1490:                 */
1491:                public String source() {
1492:                    return this .source;
1493:                }
1494:
1495:                /**
1496:                 * Returns the script's origin URL.
1497:                 */
1498:                public String url() {
1499:                    return this .url;
1500:                }
1501:
1502:                /**
1503:                 * Returns the number of FunctionSource objects stored in this object.
1504:                 */
1505:                public int functionSourcesTop() {
1506:                    return functionSources.length;
1507:                }
1508:
1509:                /**
1510:                 * Returns the FunctionSource object with the given index.
1511:                 */
1512:                public FunctionSource functionSource(int i) {
1513:                    return functionSources[i];
1514:                }
1515:
1516:                /**
1517:                 * Copies the breakpoints from the given SourceInfo object into this
1518:                 * one.
1519:                 */
1520:                private void copyBreakpointsFrom(SourceInfo old) {
1521:                    int end = old.breakpoints.length;
1522:                    if (end > this .breakpoints.length) {
1523:                        end = this .breakpoints.length;
1524:                    }
1525:                    for (int line = 0; line != end; ++line) {
1526:                        if (old.breakpoints[line]) {
1527:                            this .breakpoints[line] = true;
1528:                        }
1529:                    }
1530:                }
1531:
1532:                /**
1533:                 * Returns whether the given line number can have a breakpoint set on
1534:                 * it.
1535:                 */
1536:                public boolean breakableLine(int line) {
1537:                    return (line < this .breakableLines.length)
1538:                            && this .breakableLines[line];
1539:                }
1540:
1541:                /**
1542:                 * Returns whether there is a breakpoint set on the given line.
1543:                 */
1544:                public boolean breakpoint(int line) {
1545:                    if (!breakableLine(line)) {
1546:                        throw new IllegalArgumentException(String.valueOf(line));
1547:                    }
1548:                    return line < this .breakpoints.length
1549:                            && this .breakpoints[line];
1550:                }
1551:
1552:                /**
1553:                 * Sets or clears the breakpoint flag for the given line.
1554:                 */
1555:                public boolean breakpoint(int line, boolean value) {
1556:                    if (!breakableLine(line)) {
1557:                        throw new IllegalArgumentException(String.valueOf(line));
1558:                    }
1559:                    boolean changed;
1560:                    synchronized (breakpoints) {
1561:                        if (breakpoints[line] != value) {
1562:                            breakpoints[line] = value;
1563:                            changed = true;
1564:                        } else {
1565:                            changed = false;
1566:                        }
1567:                    }
1568:                    return changed;
1569:                }
1570:
1571:                /**
1572:                 * Removes all breakpoints from the script.
1573:                 */
1574:                public void removeAllBreakpoints() {
1575:                    synchronized (breakpoints) {
1576:                        for (int line = 0; line != breakpoints.length; ++line) {
1577:                            breakpoints[line] = false;
1578:                        }
1579:                    }
1580:                }
1581:            }
1582:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.