KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > model > repl > InteractionsDocument


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.model.repl;
35
36 import java.io.*;
37 import java.awt.print.*;
38
39 import edu.rice.cs.drjava.model.print.DrJavaBook;
40
41 import edu.rice.cs.drjava.model.FileSaveSelector;
42 import edu.rice.cs.util.UnexpectedException;
43 import edu.rice.cs.util.text.EditDocumentInterface;
44 import edu.rice.cs.util.text.EditDocumentException;
45 import edu.rice.cs.util.text.ConsoleDocument;
46 import edu.rice.cs.drjava.config.OptionListener;
47
48 /** Toolkit-independent document that provides console-like interaction with a Java interpreter.
49  * @version $Id: InteractionsDocument.java 4031 2006-11-15 22:09:06Z rcartwright $
50  */

51 public class InteractionsDocument extends ConsoleDocument {
52
53   /** Default prompt. */
54   public static final String JavaDoc DEFAULT_PROMPT = "> ";
55
56   /** Style for error messages */
57   public static final String JavaDoc ERROR_STYLE = "error";
58
59   /** Style for debugger messages */
60   public static final String JavaDoc DEBUGGER_STYLE = "debugger";
61
62   public static final String JavaDoc OBJECT_RETURN_STYLE = "object.return.style";
63   
64   public static final String JavaDoc STRING_RETURN_STYLE = "string.return.style";
65   
66   public static final String JavaDoc CHARACTER_RETURN_STYLE = "character.return.style";
67   
68   public static final String JavaDoc NUMBER_RETURN_STYLE = "number.return.style";
69   
70    /** Command-line history. It's not reset when the interpreter is reset. */
71   private final History _history;
72
73   /* Constructors */
74
75   /** Reset the document on startUp. Uses a history with configurable size.
76    * @param document the edit document to use for the model
77    */

78   public InteractionsDocument(EditDocumentInterface document, String JavaDoc banner) { this(document, new History(), banner); }
79
80   /** Reset the document on startUp. Uses a history with the given
81    * maximum size. This history will not use the config framework.
82    * @param document EditDocumentInterface to use for the model
83    * @param maxHistorySize Number of commands to remember in the history
84    */

85   public InteractionsDocument(EditDocumentInterface document, int maxHistorySize, String JavaDoc banner) {
86     this(document, new History(maxHistorySize), banner);
87   }
88   
89   /** Creates and resets the interactions document on DrJava startUp. Uses the given history.
90    * @param document EditDocumentInterface to use for the model
91    * @param history History of commands
92    */

93   public InteractionsDocument(EditDocumentInterface document, History history, String JavaDoc banner) {
94     super(document);
95     _history = history;
96     _hasPrompt = true;
97     _prompt = DEFAULT_PROMPT;
98     reset(banner);
99   }
100
101   /** Lets this document know whether an interaction is in progress.
102    * @param inProgress whether an interaction is in progress
103    */

104   public void setInProgress(boolean inProgress) {
105     acquireWriteLock();
106     _hasPrompt = ! inProgress;
107     releaseWriteLock();
108   }
109
110   /** Returns whether an interaction is currently in progress. */
111   public boolean inProgress() { return ! _hasPrompt; }
112
113   /** Resets the document to a clean state. Does not reset the history. */
114   public void reset(String JavaDoc banner) {
115     acquireWriteLock();
116     try {
117       forceRemoveText(0, _document.getLength());
118       forceInsertText(0, banner, OBJECT_RETURN_STYLE);
119       insertPrompt();
120       _history.moveEnd();
121       setInProgress(false);
122     }
123     catch (EditDocumentException e) { throw new UnexpectedException(e); }
124     finally { releaseWriteLock(); }
125   }
126
127   /** Replaces any text entered past the prompt with the current item in the history. */
128   private void _replaceCurrentLineFromHistory() {
129     try {
130       _clearCurrentInputText();
131       append(_history.getCurrent(), DEFAULT_STYLE);
132     }
133     catch (EditDocumentException ble) { throw new UnexpectedException(ble); }
134   }
135
136   /** Accessor method for the history of commands. */
137   public OptionListener<Integer JavaDoc> getHistoryOptionListener() { return _history.getHistoryOptionListener(); }
138
139   /** Adds the given text to the history of commands. */
140   public void addToHistory(String JavaDoc text) {
141     acquireWriteLock();
142     try { _history.add(text); }
143     finally { releaseWriteLock(); }
144   }
145
146   /** Saves the unedited version of the current history to a file
147    * @param selector File to save to
148    */

149   public void saveHistory(FileSaveSelector selector) throws IOException {
150     acquireReadLock(); // does not modify state of document including history
151
try { _history.writeToFile(selector); }
152     finally { releaseReadLock(); }
153   }
154
155   /** Saves the edited version of the current history to a file
156    * @param selector File to save to
157    * @param editedVersion Edited verison of the history which will be
158    * saved to file instead of the lines saved in the history. The saved
159    * file will still include any tags needed to recognize it as a saved
160    * interactions file.
161    */

162   public void saveHistory(FileSaveSelector selector, String JavaDoc editedVersion) throws IOException {
163       acquireReadLock(); // does not modify state of document including history
164
try { _history.writeToFile(selector, editedVersion); }
165       finally { releaseReadLock(); }
166   }
167
168   /** Returns the entire history as a single string. Commands should be separated by semicolons. If an entire
169    * command does not end in a semicolon, one is added.
170    */

171   public String JavaDoc getHistoryAsStringWithSemicolons() {
172     acquireReadLock();
173     try { return _history.getHistoryAsStringWithSemicolons(); }
174     finally { releaseReadLock(); }
175   }
176
177   /** Returns the entire history as a single string. Commands should be separated by semicolons. */
178   public String JavaDoc getHistoryAsString() {
179     acquireReadLock();
180     try { return _history.getHistoryAsString(); }
181     finally { releaseReadLock(); }
182   }
183
184   /** Clears the history */
185   public void clearHistory() {
186     acquireWriteLock();
187     try { _history.clear(); }
188     finally { releaseWriteLock(); }
189   }
190   
191   public String JavaDoc lastEntry() {
192     acquireReadLock();
193     try { return _history.lastEntry(); } // may throw a RuntimeException if no such entry
194
finally { releaseReadLock(); }
195   }
196   /** Puts the previous line from the history on the current line and moves the history back one line.
197    * @param entry the current entry (perhaps edited from what is in history)
198    */

199   public void moveHistoryPrevious(String JavaDoc entry) {
200     acquireWriteLock();
201     try {
202       _history.movePrevious(entry);
203       _replaceCurrentLineFromHistory();
204     }
205     finally { releaseWriteLock(); }
206   }
207   
208   /** Puts the next line from the history on the current line and moves the history forward one line.
209    * @param entry the current entry (perhaps edited from what is in history)
210    */

211   public void moveHistoryNext(String JavaDoc entry) {
212     acquireWriteLock();
213     try {
214       _history.moveNext(entry);
215       _replaceCurrentLineFromHistory();
216     }
217    finally { releaseWriteLock(); }
218   }
219   
220   /** Returns whether there is a previous command in the history. */
221   public boolean hasHistoryPrevious() {
222     acquireReadLock();
223     try { return _history.hasPrevious(); }
224     finally { releaseReadLock(); }
225   }
226
227   /** Returns whether there is a next command in the history. */
228   public boolean hasHistoryNext() {
229     acquireReadLock();
230     try { return _history.hasNext(); }
231     finally { releaseReadLock(); }
232   }
233   
234   /** Reverse searches the history for the given string.
235    * @param searchString the string to search for
236    */

237   public void reverseHistorySearch(String JavaDoc searchString) {
238     acquireWriteLock();
239     try {
240       _history.reverseSearch(searchString);
241       _replaceCurrentLineFromHistory();
242     }
243     finally { releaseWriteLock(); }
244   }
245   
246   /** Forward searches the history for the given string.
247    * @param searchString the string to search for
248    */

249   public void forwardHistorySearch(String JavaDoc searchString) {
250     acquireWriteLock();
251     try {
252       _history.forwardSearch(searchString);
253       _replaceCurrentLineFromHistory();
254     }
255     finally { releaseWriteLock(); }
256   }
257   
258   /** Gets the previous interaction in the history and replaces whatever is on the current interactions input
259    * line with this interaction.
260    */

261   public boolean recallPreviousInteractionInHistory() {
262     acquireWriteLock();
263     try {
264       if (hasHistoryPrevious()) {
265         moveHistoryPrevious(getCurrentInteraction());
266         return true;
267       }
268       _beep.run();
269       return false;
270     }
271     finally { releaseWriteLock(); }
272   }
273   
274   /** Gets the next interaction in the history and replaces whatever is on the current interactions input line
275    * with this interaction.
276    */

277   public boolean recallNextInteractionInHistory() {
278     acquireWriteLock();
279     try {
280       if (hasHistoryNext()) {
281         moveHistoryNext(getCurrentInteraction());
282         return true;
283       }
284       _beep.run();
285       return false;
286     }
287     finally { releaseWriteLock(); }
288   }
289   
290
291   /** Reverse searches the history for interactions that started with the current interaction. */
292   public void reverseSearchInteractionsInHistory() {
293     acquireWriteLock();
294     try {
295       if (hasHistoryPrevious()) reverseHistorySearch(getCurrentInteraction());
296       else _beep.run();
297     }
298     finally { releaseWriteLock(); }
299   }
300   
301   /** Forward searches the history for interactions that started with the current interaction. */
302   public void forwardSearchInteractionsInHistory() {
303     acquireWriteLock();
304     try {
305       if (hasHistoryNext()) forwardHistorySearch(getCurrentInteraction());
306       else _beep.run();
307     }
308     finally { releaseWriteLock(); }
309   }
310   
311   /** Inserts the given exception data into the document with the given style.
312    * @param exceptionClass Name of the exception that was thrown
313    * @param message Message contained in the exception
314    * @param stackTrace String representation of the stack trace
315    * @param styleName name of the style for formatting the exception
316    */

317   public void appendExceptionResult(String JavaDoc exceptionClass, String JavaDoc message, String JavaDoc stackTrace, String JavaDoc styleName) {
318     // TODO: should probably log this error, or figure out what causes it
319
// it does not seem to affect the program negatively, though
320
if ((message!=null) && (message.equals("Connection refused to host: 127.0.0.1; nested exception is: \n" +
321                                            "\tjava.net.ConnectException: Connection refused: connect"))) return;
322
323     if (null == message || "null".equals(message)) message = "";
324     
325     // Simplify the common error messages
326
if ("koala.dynamicjava.interpreter.error.ExecutionError".equals(exceptionClass) ||
327         "edu.rice.cs.drjava.model.repl.InteractionsException".equals(exceptionClass)) {
328       exceptionClass = "Error";
329     }
330     
331     // The following is an ugly hack that should be fixed ASAP. The read/writelock methods need to be added to
332
// the EditDocumentInterface interface. This cast and a similar one in ConsoleDocument must be removed because they
333
// defeat the purpose of the EditDocumentInterface interface.
334

335     String JavaDoc c = exceptionClass;
336     if (c.indexOf('.') != -1) c = c.substring(c.lastIndexOf('.') + 1, c.length());
337     
338     acquireWriteLock();
339     try {
340       append(c + ": " + message + "\n", styleName);
341       
342       // An example stack trace:
343
//
344
// java.lang.IllegalMonitorStateException:
345
// at java.lang.Object.wait(Native Method)
346
// at java.lang.Object.wait(Object.java:425)
347
if (! stackTrace.trim().equals("")) {
348         BufferedReader reader = new BufferedReader(new StringReader(stackTrace));
349         
350         String JavaDoc line;
351         // a line is parsable if it has ( then : then ), with some
352
// text between each of those
353
while ((line = reader.readLine()) != null) {
354           String JavaDoc fileName;
355           int lineNumber;
356           
357           // TODO: Why is this stuff here??
358
int openLoc = line.indexOf('(');
359           if (openLoc != -1) {
360             int closeLoc = line.indexOf(')', openLoc + 1);
361             
362             if (closeLoc != -1) {
363               int colonLoc = line.indexOf(':', openLoc + 1);
364               if ((colonLoc > openLoc) && (colonLoc < closeLoc)) {
365                 // ok this line is parsable!
366
String JavaDoc lineNumStr = line.substring(colonLoc + 1, closeLoc);
367                 try {
368                   lineNumber = Integer.parseInt(lineNumStr);
369                   fileName = line.substring(openLoc + 1, colonLoc);
370                 }
371                 catch (NumberFormatException JavaDoc nfe) {
372                   // do nothing; we failed at parsing
373
}
374               }
375             }
376           }
377           
378           append(line, styleName);
379           
380           //JOptionPane.showMessageDialog(null, "\\n");
381
append("\n", styleName);
382           
383         } // end the while
384
}
385     }
386     catch (IOException ioe) { throw new UnexpectedException(ioe); }
387     catch (EditDocumentException ble) { throw new UnexpectedException(ble); }
388     finally { releaseWriteLock(); }
389   }
390
391   public void appendSyntaxErrorResult(String JavaDoc message, String JavaDoc interaction, int startRow, int startCol,
392                                       int endRow, int endCol, String JavaDoc styleName) {
393     try {
394       if (null == message || "null".equals(message)) message = "";
395       
396       if (message.indexOf("Lexical error") != -1) {
397         int i = message.lastIndexOf(':');
398         if (i != -1) message = "Syntax Error:" + message.substring(i+2, message.length());
399       }
400       
401       if (message.indexOf("Error") == -1) message = "Error: " + message;
402       
403       append(message + "\n" , styleName);
404     }
405     catch (EditDocumentException ble) { throw new UnexpectedException(ble); }
406   }
407
408   /** Clears the current input text and then moves to the end of the command history. */
409   public void clearCurrentInteraction() {
410     acquireWriteLock();
411     try {
412       super.clearCurrentInput();
413       _history.moveEnd();
414     }
415     finally { releaseWriteLock(); }
416   }
417
418   /** Returns the string that the user has entered at the current prompt. Forwards to getCurrentInput(). */
419   public String JavaDoc getCurrentInteraction() { return getCurrentInput(); }
420   
421   public String JavaDoc getDefaultStyle() { return InteractionsDocument.DEFAULT_STYLE; }
422   
423   /** This method tells the document to prepare all the DrJavaBook and PagePrinter objects. */
424   public void preparePrintJob() {
425     _book = new DrJavaBook(getDocText(0, getLength()), "Interactions", new PageFormat());
426   }
427   
428   /* Only used for testing. */
429   protected History getHistory() { return _history; }
430 }
431
Popular Tags