/[svn]/jsampler/trunk/src/org/jsampler/DefaultLSConsoleModel.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/DefaultLSConsoleModel.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1143 - (show annotations) (download)
Mon Apr 2 21:18:31 2007 UTC (17 years ago) by iliev
File size: 14537 byte(s)
* upgrading to version 0.4a

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2006 Grigor Iliev <grigor@grigoriliev.com>
5 *
6 * This file is part of JSampler.
7 *
8 * JSampler is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * JSampler is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with JSampler; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23 package org.jsampler;
24
25 import java.awt.event.ActionEvent;
26 import java.awt.event.ActionListener;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.io.UnsupportedEncodingException;
32
33 import java.net.Socket;
34
35 import java.util.LinkedList;
36 import java.util.Vector;
37
38 import java.util.logging.Level;
39
40 import javax.swing.SwingUtilities;
41
42 import net.sf.juife.event.TaskEvent;
43 import net.sf.juife.event.TaskListener;
44
45 import org.jsampler.event.LSConsoleEvent;
46 import org.jsampler.event.LSConsoleListener;
47
48 import org.jsampler.task.LSConsoleConnect;
49
50 import static org.jsampler.JSI18n.i18n;
51
52
53 /**
54 * This class provides default implementation of the <code>LSConsoleModel</code> interface.
55 * @author Grigor Iliev
56 */
57 public class DefaultLSConsoleModel implements LSConsoleModel {
58 private Socket socket;
59 private LscpOutputStream out;
60
61 private final String[] cmdList = LscpUtils.getCommandList();
62
63 private String cmdLine = "";
64
65 /**
66 * Contains the global command history, excluding blank lines and comments.
67 */
68 private final LinkedList<String> cmdHistory = new LinkedList<String>();
69
70 private int cmdHistoryIdx = -1;
71
72 private int commandHistorySize = 1000;
73
74 private final LSConsoleThread lsConsoleThread = new LSConsoleThread();
75
76 /**
77 * Contains the command history of the current
78 * session, including blank lines and comments.
79 */
80 private final Vector<String> sessionHistory = new Vector<String>();
81
82 /** Used to hold the current command when browsing through command history, etc. */
83 private String currentCmd = "";
84
85 private final Vector<LSConsoleListener> listeners = new Vector<LSConsoleListener>();
86
87
88 /** Creates a new instance of <code>DefaultLSConsoleModel</code>. */
89 public
90 DefaultLSConsoleModel() {
91 reconnect();
92
93 CC.addReconnectListener(new ActionListener() {
94 public void
95 actionPerformed(ActionEvent e) { reconnect(); }
96 });
97
98 lsConsoleThread.start();
99 }
100
101 private Socket
102 getSocket() { return socket; }
103
104 private void
105 setSocket(Socket socket) { this.socket = socket; }
106
107 private void
108 reconnect() {
109 final LSConsoleConnect cnt = new LSConsoleConnect(getSocket());
110
111 cnt.addTaskListener(new TaskListener() {
112 public void
113 taskPerformed(TaskEvent e) { changeSocket(cnt.getResult()); }
114 });
115
116 CC.getTaskQueue().add(cnt);
117 }
118
119 private void
120 changeSocket(Socket sock) {
121 setSocket(sock);
122
123 try {
124 LscpInputStream in;
125 in = sock == null ? null : new LscpInputStream(sock.getInputStream());
126 out = sock == null ? null : new LscpOutputStream(sock.getOutputStream());
127
128 lsConsoleThread.setInputStream(in);
129 } catch(Exception x) { CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x); }
130 }
131
132 /**
133 * Registers the specified listener for receiving event messages.
134 * @param l The <code>LSConsoleListener</code> to register.
135 */
136 public void
137 addLSConsoleListener(LSConsoleListener l) { listeners.add(l); }
138
139 /**
140 * Removes the specified listener.
141 * @param l The <code>LSConsoleListener</code> to remove.
142 */
143 public void
144 removeLSConsoleListener(LSConsoleListener l) { listeners.remove(l); }
145
146 /** Executes the command specified in the command line. */
147 public void
148 execCommand() {
149 String cmd = getCommandLineText();
150 sessionHistory.add(cmd);
151 if(cmd.trim().length() > 0 && !cmd.startsWith("#")) addToCommandHistory(cmd);
152 while(cmdHistory.size() > getCommandHistorySize()) cmdHistory.removeFirst();
153
154 setCommandLineText("");
155 currentCmd = "";
156 cmdHistoryIdx = -1;
157
158 if( getSocket() == null || getSocket().isClosed() || !getSocket().isConnected()
159 || getSocket().isOutputShutdown() || out == null ) {
160
161 fireResponseReceived(i18n.getMessage("DefaultLSConsoleModel.notConnected"));
162 } else {
163 CC.getTaskQueue().add(new LSConsoleExecCommand(cmd));
164 }
165
166 fireCommandExecuted();
167 }
168
169 /**
170 * Gets the last executed command.
171 * @return The last command executed in the LS Console.
172 */
173 public String
174 getLastExecutedCommand() {
175 int size = sessionHistory.size();
176 return size == 0 ? "" : sessionHistory.get(size - 1);
177 }
178
179 /**
180 * Sets the text in the command line.
181 * @param cmdLine The new command line text.
182 */
183 public void
184 setCommandLineText(String cmdLine) {
185 if(this.cmdLine.equals(cmdLine)) return;
186
187 String oldCmdLine = this.cmdLine;
188 this.cmdLine = cmdLine;
189 fireCommandLineTextChanged(oldCmdLine);
190 }
191
192 /**
193 * Gets the text in the command line.
194 * @return The command line's text.
195 */
196 public String
197 getCommandLineText() { return cmdLine; }
198
199 /**
200 * Gets the command history of the current session, including blank lines and comments.
201 * @return The command history of the current session, including blank lines and comments.
202 */
203 public String[]
204 getSessionHistory() {
205 return sessionHistory.toArray(new String[sessionHistory.size()]);
206 }
207
208 /**
209 * Clears the session history.
210 * @see #getSessionHistory
211 */
212 public void
213 clearSessionHistory() { sessionHistory.removeAllElements(); }
214
215 /**
216 * Adds the specified <code>command</code> to command history.
217 * @param command The command to be added to command history.
218 */
219 public void
220 addToCommandHistory(String command) { cmdHistory.add(command); }
221
222 /**
223 * Gets the complete command history, excluding blank lines and comments.
224 * @return The complete command history, excluding blank lines and comments.
225 */
226 public String[]
227 getCommandHistory() {
228 return cmdHistory.toArray(new String[cmdHistory.size()]);
229 }
230
231 /**
232 * Clears the complete/multisession command history.
233 * @see #getCommandHistory
234 */
235 public void
236 clearCommandHistory() {
237 cmdHistory.clear();
238 cmdHistoryIdx = -1;
239 }
240
241 /**
242 * Determines the maximum number of lines to be kept in the command history.
243 * @return The maximum number of lines to be kept in the command history.
244 */
245 public int
246 getCommandHistorySize() { return commandHistorySize; }
247
248 /**
249 * Sets the maximum number of lines to be kept in the command history.
250 * @param size Determines the maximum number of lines to be kept in the command history.
251 */
252 public void
253 setCommandHistorySize(int size) { commandHistorySize = size; }
254
255 /**
256 * Gets a list of all LSCP commands.
257 * @return A list of all LSCP commands.
258 */
259 public String[]
260 getCommandList() { return cmdList; }
261
262 /** Browses the command history one line up. */
263 public void
264 browseCommandHistoryUp() {
265 if(cmdHistory.size() == 0) return;
266
267 if(cmdHistoryIdx == -1) {
268 currentCmd = getCommandLineText();
269 cmdHistoryIdx = cmdHistory.size() - 1;
270 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
271 return;
272 }
273
274 if(cmdHistoryIdx == 0) return;
275
276 setCommandLineText(cmdHistory.get(--cmdHistoryIdx));
277 }
278
279 /** Browses the command history one line down. */
280 public void
281 browseCommandHistoryDown() {
282 if(cmdHistory.size() == 0 || cmdHistoryIdx == -1) return;
283 if(cmdHistoryIdx == cmdHistory.size() - 1) {
284 cmdHistoryIdx = -1;
285 setCommandLineText(currentCmd);
286 currentCmd = "";
287 return;
288 }
289
290 setCommandLineText(cmdHistory.get(++cmdHistoryIdx));
291 }
292
293 /** Browses to the first line of the command history. */
294 public void
295 browseCommandHistoryFirst() {
296 if(cmdHistory.size() == 0) return;
297 cmdHistoryIdx = 0;
298 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
299 }
300
301 /** Browses to the last line of the command history. */
302 public void
303 browseCommandHistoryLast() {
304 if(cmdHistory.size() == 0) return;
305 cmdHistoryIdx = cmdHistory.size() - 1;
306 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
307 }
308
309 private Vector<String> tmpVector = new Vector<String>();
310
311 /**
312 * Searches the command history for commands
313 * containing the string returned by {@link #getCommandLineText}.
314 * @return All commands that contains the string returned by {@link #getCommandLineText}.
315 * @see #getCommandHistory
316 */
317 public String[]
318 searchCommandHistory() { return searchCommandHistory(getCommandLineText()); }
319
320 /**
321 * Searches the command history for commands containing <code>substring</code>.
322 * @param substring The substring to be used to perform the search.
323 * @return All commands that contains <code>substring</code>.
324 * @see #getCommandList
325 */
326 public String[]
327 searchCommandHistory(String substring) {
328 tmpVector.removeAllElements();
329 for(String s : cmdHistory) if(s.indexOf(substring) != -1) tmpVector.add(s);
330
331 return tmpVector.toArray(new String[tmpVector.size()]);
332 }
333
334 /**
335 * Searches the LSCP command list for commands
336 * containing the string returned by {@link #getCommandLineText}.
337 * @return All commands that contains the string returned by {@link #getCommandLineText}.
338 * @see #getCommandList
339 */
340 public String[]
341 searchCommandList() { return searchCommandList(getCommandLineText()); }
342
343 /**
344 * Searches the LSCP command list for commands containing <code>substring</code>.
345 * @param substring The substring to be used to perform the search.
346 * @return All commands that contains <code>substring</code>.
347 * @see #getCommandList
348 */
349 public String[]
350 searchCommandList(String substring) {
351 tmpVector.removeAllElements();
352 for(String s : cmdList) if(s.indexOf(substring) != -1) tmpVector.add(s);
353
354 return tmpVector.toArray(new String[tmpVector.size()]);
355 }
356
357 /** Notifies listeners that the text in the command line has changed. */
358 private void
359 fireCommandLineTextChanged(String oldCmdLine) {
360 LSConsoleEvent e = new LSConsoleEvent(this, null, oldCmdLine);
361 for(LSConsoleListener l : listeners) l.commandLineTextChanged(e);
362 }
363
364 /** Notifies listeners that the command in the command line has been executed. */
365 private void
366 fireCommandExecuted() {
367 LSConsoleEvent e = new LSConsoleEvent(this);
368 for(LSConsoleListener l : listeners) l.commandExecuted(e);
369 }
370
371 /**
372 * Notifies listeners that response is received from LinuxSampler.
373 * @param response The response received from LinuxSampler.
374 */
375 private void
376 fireResponseReceived(final String response) {
377 SwingUtilities.invokeLater(new Runnable() {
378 public void
379 run() {
380 LSConsoleEvent e = new LSConsoleEvent(this, response);
381 for(LSConsoleListener l : listeners) l.responseReceived(e);
382 }
383 });
384 }
385
386 /** Executes LS Console command. */
387 private class LSConsoleExecCommand extends org.jsampler.task.EnhancedTask {
388 private String cmd;
389
390 /** Creates a new instance of <code>LSConsoleExecCommand</code>. */
391 public
392 LSConsoleExecCommand(String cmd) {
393 setTitle("LSConsoleExecCommand_task");
394 setDescription(i18n.getMessage("LSConsoleExecCommand.description"));
395 this.cmd = cmd;
396 }
397
398 /** The entry point of the task. */
399 public void
400 run() {
401 try { out.writeLine(cmd); }
402 catch(Exception x) {
403 setErrorMessage(getDescription() + ": " + HF.getErrorMessage(x));
404 CC.getLogger().log(Level.FINE, getErrorMessage(), x);
405 }
406 }
407 }
408
409 class LSConsoleThread extends Thread {
410 LscpInputStream in;
411 private boolean terminate = false;
412
413 LSConsoleThread() {super("LS-Console-Thread"); }
414
415 public void
416 run() {
417 while(!mustTerminate()) {
418 try { processInput(); }
419 catch(Exception x) {
420 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
421 }
422
423 try { synchronized(this) { wait(100); } }
424 catch(Exception x) {
425 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
426 }
427 }
428 }
429
430 private synchronized boolean
431 mustTerminate() { return terminate; }
432
433 public synchronized void
434 terminate() {
435 terminate = true;
436 this.notifyAll();
437 }
438
439 /** Processes the input sent by LinuxSampler */
440 private synchronized void
441 processInput() throws IOException {
442 while(in != null && in.available() > 0) {
443 String response = in.readLine();
444 fireResponseReceived(response);
445 }
446 }
447
448 public synchronized void
449 setInputStream(LscpInputStream in) { this.in = in; }
450 }
451
452 class LscpInputStream {
453 private InputStream in;
454 private StringBuffer buf = new StringBuffer();
455
456 /**
457 * Creates a new instance of LscpInputStream.
458 *
459 */
460 public
461 LscpInputStream(InputStream in) {
462 this.in = in;
463 }
464
465 /**
466 * Reads a line.
467 * This method is thread safe.
468 *
469 * @return A string containing the next line readed from the stream or
470 * <code>null</code> if the end of the stream has been reached.
471 * @throws IOException If an I/O error occurs.
472 */
473 public synchronized String
474 readLine() throws IOException {
475 int i;
476 buf.setLength(0);
477
478 while((i = in.read()) != -1) {
479 if(i == '\r') {
480 checkLF();
481 break;
482 }
483 buf.append((char)i);
484 }
485
486 if(i == -1) {
487 if(buf.length() > 0)
488 throw new IOException("Unexpected end of line!");
489 return null;
490 }
491 return buf.toString();
492 }
493
494 /**
495 * Returns the number of bytes that can
496 * be read from this input stream without blocking.
497 *
498 * @return The number of bytes that can
499 * be read from this input stream without blocking.
500 * @throws IOException If an I/O error occurs.
501 */
502 public synchronized int
503 available() throws IOException { return in.available(); }
504
505 private void
506 checkLF() throws IOException {
507 int i = in.read();
508 if(i == -1) throw new IOException("Unexpected end of file!");
509 if(i != '\n') throw new IOException("Unexpected end of line!");
510 }
511 }
512
513 class LscpOutputStream {
514 private OutputStream out;
515
516 /** Creates a new instance of LscpOutputStream */
517 public
518 LscpOutputStream(OutputStream out) { this.out = out; }
519
520 /*
521 * Writes a line.
522 * @param line a string to be written.
523 */
524 public void
525 writeLine(String line) throws IOException {
526 try {
527 out.write(line.getBytes("US-ASCII"));
528 out.write('\r');
529 out.write('\n');
530 out.flush();
531 } catch(UnsupportedEncodingException x) {
532 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
533 }
534 }
535 }
536 }

  ViewVC Help
Powered by ViewVC