KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bsf > engines > javascript > FnOrScript


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if
20  * any, must include the following acknowlegement:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowlegement may appear in the software itself,
24  * if and wherever such third-party acknowlegements normally appear.
25  *
26  * 4. The names "Apache BSF", "Apache", and "Apache Software Foundation"
27  * must not be used to endorse or promote products derived from
28  * this software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache"
32  * nor may "Apache" appear in their names without prior written
33  * permission of the Apache Group.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many individuals
50  * on behalf of the Apache Software Foundation and was originally created by
51  * Sanjiva Weerawarana and others at International Business Machines
52  * Corporation. For more information on the Apache Software Foundation,
53  * please see <http://www.apache.org/>.
54  */

55
56 package org.apache.bsf.engines.javascript;
57
58 import java.util.Vector JavaDoc;
59 import java.util.Hashtable JavaDoc;
60 import java.util.Enumeration JavaDoc;
61
62 import org.apache.bsf.*;
63
64 import java.io.IOException JavaDoc;
65 import java.io.Reader JavaDoc;
66 import java.io.StringReader JavaDoc;
67 import org.mozilla.javascript.debug.*;
68 import org.mozilla.javascript.*;
69
70 /**
71  * This class represents a function or script, that is,
72  * a piece of a document that is provided to the JavaScript
73  * engine for evaluation, execution, or simply compilation.
74  *
75  * A FnOrScript represents a range of lines or characters
76  * in its document. For now, Rhino only supports ranges
77  * of lines, really, but the code for offsets is there anyway.
78  *
79  * Warning: Offsets have never been quite tested yet...
80  *
81  * A FnOrScript has compilation units. When Rhino compiles
82  * a function or a script, even in interpreted mode where the
83  * compilation is done to JavaScript bytecode, it calls back
84  * its debugger with different compilation units; see
85  * Debugger::handleCompilationDone method on the RhinoEngineDebugger
86  * class.
87  *
88  * A FnOrScript also keeps track of the known breakpoints
89  * in its range of lines or characters. It makes sure
90  * that they are propagated to the underlying Rhino
91  * engine (i.e. set) as well as unpropagated (i.e. unset).
92  *
93  * @author: Olivier Gruber
94  */

95 public class FnOrScript {
96
97     protected DocumentCell m_cell;
98     protected boolean m_lineDefined;
99     protected int m_startLine, m_lineCount, m_column;
100     protected int m_offset, m_charCount;
101
102     protected Vector JavaDoc m_breakpoints;
103
104     protected StringBuffer JavaDoc m_text;
105
106     protected Vector JavaDoc m_units; // of CompilationUnit.
107
protected Script m_script;
108
109     protected Hashtable JavaDoc m_functionMap;
110
111     public FnOrScript(DocumentCell cell) {
112         m_cell = cell;
113         m_lineDefined = true;
114         m_startLine = -1;
115         m_column = -1;
116         m_lineCount = 0;
117         m_breakpoints = new Vector JavaDoc();
118         m_text = new StringBuffer JavaDoc();
119     
120         m_units = new Vector JavaDoc();
121         m_functionMap = new Hashtable JavaDoc();
122     }
123
124     private BreakPoint _addBreakpoint(BreakPoint bp) {
125         bp = createBreakpoint(bp);
126         m_breakpoints.addElement(bp);
127         return bp;
128     }
129
130     public BreakPoint addBreakpoint(BreakPoint bp) {
131
132         m_breakpoints.addElement(bp);
133
134         // now, look for a unit containing it and
135
// if one is found, set the breakpoint unit
136
// and propagate...
137
Enumeration JavaDoc e;
138         CompilationUnit unit;
139         e = m_units.elements();
140         while (e.hasMoreElements()) {
141             unit = (CompilationUnit) e.nextElement();
142             if (unit.contains(bp)) {
143                 bp.setUnit(unit);
144                 bp.propagate();
145                 break;
146             }
147         }
148         return bp;
149     }
150     
151     private BreakPoint _removeBreakpoint(int brkptId) {
152         Enumeration JavaDoc e;
153         BreakPoint bp;
154
155         e = m_breakpoints.elements();
156         while (e.hasMoreElements()) {
157             bp = (BreakPoint) e.nextElement();
158             if (brkptId == bp.getId()) {
159                 m_breakpoints.removeElement(bp);
160                 return bp;
161             }
162         }
163         return null;
164     }
165
166     public BreakPoint removeBreakpoint(int bpid) {
167
168         Enumeration JavaDoc e;
169         BreakPoint bp;
170
171         e = m_breakpoints.elements();
172         while (e.hasMoreElements()) {
173             bp = (BreakPoint) e.nextElement();
174             if (bpid == bp.getId()) {
175                 m_breakpoints.removeElement(bp);
176                 bp.unpropagate();
177                 return bp;
178             }
179         }
180         return null;
181     }
182     
183     boolean contains(BreakPoint bp) throws BSFException {
184         if (m_lineDefined) {
185             int line = bp.getLineNo();
186             return (m_startLine <= line && line < m_startLine + m_lineCount);
187         } else {
188             int offset = bp.getOffset();
189             return (m_offset <= offset && offset < m_offset + m_charCount);
190         }
191     }
192
193     //-----------------------------------------
194
// This protected method works as a factory
195
// for language-specific breakpoints.
196
// The default behavior is to use the provided
197
// generic breakpoint.
198
// See javascript for an example of language-specific
199
// breakpoints.
200

201     protected BreakPoint createBreakpoint(BreakPoint bp) {
202         return bp;
203     }
204
205     public BreakPoint findBreakpointAtLine(int lineno) throws BSFException {
206         Enumeration JavaDoc e;
207         BreakPoint bp;
208
209         if (!m_lineDefined)
210             throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
211                                    "Function or Script is defined with ranges, lines are not supported.");
212
213         e = m_breakpoints.elements();
214         while (e.hasMoreElements()) {
215             bp = (BreakPoint) e.nextElement();
216             if (lineno == bp.getLineNo())
217                 return bp;
218         }
219         return null;
220     }
221
222     public BreakPoint findBreakpointAtOffset(int offset) throws BSFException {
223         Enumeration JavaDoc e;
224         BreakPoint bp;
225
226         if (m_lineDefined)
227             throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
228                                    "Function or Script is defined with lines, offsets are not supported.");
229
230         e = m_breakpoints.elements();
231         while (e.hasMoreElements()) {
232             bp = (BreakPoint) e.nextElement();
233             if (offset == bp.getOffset())
234                 return bp;
235         }
236         return null;
237     }
238
239     public int getCharCount() throws BSFException {
240         if (!m_lineDefined)
241             return m_charCount;
242         throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
243                                "Function or Script is defined with ranges, lines are not supported.");
244     }
245     public DocumentCell getDocument() {
246         return m_cell;
247     }
248
249     public int getFirstLine() throws BSFException {
250         if (m_lineDefined)
251             return m_startLine;
252         throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
253                                "Function or Script is defined with ranges, lines are not supported.");
254     }
255
256     public int getColumn() throws BSFException {
257         if (m_lineDefined)
258             return m_column;
259         throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
260                                "Function or Script is defined with ranges, lines are not supported.");
261     }
262
263     public StringBuffer JavaDoc getFnOrScriptAsStringBuffer() {
264         return m_text;
265     }
266
267     public int getLineCount() throws BSFException {
268         if (m_lineDefined)
269             return m_lineCount;
270         throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
271                                "Function or Script is defined with ranges, lines are not supported.");
272     }
273
274     public int getOffset() throws BSFException {
275         if (!m_lineDefined)
276             return m_offset;
277         throw new BSFException(BSFException.REASON_INVALID_ARGUMENT,
278                                "Function or Script is defined with ranges, lines are not supported.");
279     }
280
281     private void readChars(Reader JavaDoc reader) {
282         char chars[] = new char[256];
283         char c;
284         int n, charCount;
285         String JavaDoc line;
286         charCount = 0;
287         n = 0;
288         try {
289             while (true) {
290                 n = reader.read(chars, 0, 256);
291                 if (n == -1)
292                     break;
293                 m_text.append(chars, 0, n);
294                 charCount += n;
295             }
296             m_charCount = charCount;
297         } catch (IOException JavaDoc ex) {
298         }
299     }
300
301     private void readLines(Reader JavaDoc reader) {
302         char chars[] = new char[256];
303         char c;
304         int n, val, lineCount;
305         String JavaDoc line;
306         lineCount = 0;
307         n = 0;
308         while (true) {
309             if (n >= chars.length) {
310                 char tmp[] = chars;
311                 chars = new char[2 * chars.length];
312                 System.arraycopy(chars, 0, tmp, 0, tmp.length);
313             }
314             try {
315                 val = reader.read();
316             } catch (IOException JavaDoc ex) {
317                 val = -1;
318             }
319             if (val == -1)
320                 break;
321             c = (char) val;
322             chars[n++] = c;
323             if (c == '\n') {
324                 line = new String JavaDoc(chars, 0, n);
325                 m_text.append(line);
326                 n = 0;
327                 lineCount++;
328             }
329         }
330         // Don't forget the last line if it is not
331
// terminated by a \n
332
if (n != 0) {
333             line = new String JavaDoc(chars, 0, n);
334             m_text.append(line);
335             lineCount++;
336         }
337         m_lineCount = lineCount;
338     }
339
340     public void specifyLinesPos(Reader JavaDoc reader, int startLine, int column)
341         throws BSFException, IOException JavaDoc {
342         m_startLine = startLine;
343         m_column = column;
344         m_lineCount = -1;
345         m_charCount = -1;
346         m_offset = -1;
347         m_lineDefined = true;
348         readLines(reader);
349     }
350
351     public void specifyRange(Reader JavaDoc reader, int offset)
352         throws BSFException, IOException JavaDoc {
353         m_offset = offset;
354         m_charCount = -1;
355         m_startLine = -1;
356         m_lineCount = -1;
357         m_lineDefined = false;
358         readChars(reader);
359     }
360
361     public void addCompilationUnit(Context cx,
362                                    DebuggableScript dbgScript,
363                                    StringBuffer JavaDoc source) {
364
365         CompilationUnit unit;
366
367         unit = new CompilationUnit(this, dbgScript);
368         m_units.addElement(unit);
369         if (unit.m_fnName != null) {
370             m_functionMap.put(unit.m_fnName, unit);
371         }
372
373         // Associate breakpoints to this unit if
374
// the unit contains them...
375
Enumeration JavaDoc e;
376         BreakPoint bp;
377         e = m_breakpoints.elements();
378         while (e.hasMoreElements()) {
379             bp = (BreakPoint) e.nextElement();
380             if (unit.contains(bp))
381                 bp.setUnit(unit);
382         }
383         propagateAll();
384     }
385
386     public void compile(Context cx, Scriptable global)
387         throws BSFException, IOException JavaDoc {
388
389         Enumeration JavaDoc e;
390         Reader JavaDoc reader = new StringReader JavaDoc(m_text.toString());
391         m_script =
392             cx.compileReader(global, reader, m_cell.getName(),
393                              m_startLine, null);
394         if (m_script == null)
395             throw new BSFException("Compilation of the script "
396                                    + m_cell.getName()
397                                    + " failed at line "
398                                    + m_startLine);
399     }
400
401     boolean contains(CompilationUnit unit) {
402         return (m_startLine <= unit.m_firstLine
403                 && unit.m_firstLine + unit.m_lineCount <=
404                 m_startLine + m_lineCount);
405     }
406
407     public Script getScript() {
408         return m_script;
409     }
410
411     private void propagateAll() {
412         Enumeration JavaDoc e;
413         BreakPoint bp;
414         e = m_breakpoints.elements();
415         while (e.hasMoreElements()) {
416             bp = (BreakPoint) e.nextElement();
417             bp.propagate();
418         }
419     }
420 }
421
Popular Tags