/[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 1786 - (show annotations) (download)
Wed Oct 8 22:38:15 2008 UTC (15 years, 6 months ago) by iliev
File size: 14931 byte(s)
* Implemented option to launch the backend if it is not yet started
  (choose Edit/Preferences, then click the `Backend' tab)
* LSCP scripts can now be run by passing them to jsampler
  as command-line arguments
* The scripts in the `scripts' directory now pass the command-line
  arguments to the respective jsampler distribution
* ant: the default target is now build-fantasia
* bugfix: backend address was always set to 127.0.0.1 when adding
  backend to the backend list

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2008 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 CC.addReconnectListener(new ActionListener() {
92 public void
93 actionPerformed(ActionEvent e) { reconnect(); }
94 });
95
96 lsConsoleThread.start();
97 }
98
99 private Socket
100 getSocket() { return socket; }
101
102 private void
103 setSocket(Socket socket) { this.socket = socket; }
104
105 private void
106 reconnect() {
107 final LSConsoleConnect cnt = new LSConsoleConnect(getSocket());
108
109 cnt.addTaskListener(new TaskListener() {
110 public void
111 taskPerformed(TaskEvent e) { changeSocket(cnt.getResult()); }
112 });
113
114 CC.getTaskQueue().add(cnt);
115 }
116
117 public void
118 disconnect() {
119 try { if(getSocket() != null) getSocket().close(); }
120 catch(Exception x) { CC.getLogger().info(HF.getErrorMessage(x)); }
121 }
122
123 private void
124 changeSocket(Socket sock) {
125 setSocket(sock);
126
127 try {
128 LscpInputStream in;
129 in = sock == null ? null : new LscpInputStream(sock.getInputStream());
130 out = sock == null ? null : new LscpOutputStream(sock.getOutputStream());
131
132 lsConsoleThread.setInputStream(in);
133 } catch(Exception x) { CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x); }
134 }
135
136 /**
137 * Registers the specified listener for receiving event messages.
138 * @param l The <code>LSConsoleListener</code> to register.
139 */
140 @Override
141 public void
142 addLSConsoleListener(LSConsoleListener l) { listeners.add(l); }
143
144 /**
145 * Removes the specified listener.
146 * @param l The <code>LSConsoleListener</code> to remove.
147 */
148 @Override
149 public void
150 removeLSConsoleListener(LSConsoleListener l) { listeners.remove(l); }
151
152 /** Executes the command specified in the command line. */
153 @Override
154 public void
155 execCommand() {
156 String cmd = getCommandLineText();
157 sessionHistory.add(cmd);
158 if(cmd.trim().length() > 0 && !cmd.startsWith("#")) addToCommandHistory(cmd);
159 while(cmdHistory.size() > getCommandHistorySize()) cmdHistory.removeFirst();
160
161 setCommandLineText("");
162 currentCmd = "";
163 cmdHistoryIdx = -1;
164
165 if( getSocket() == null || getSocket().isClosed() || !getSocket().isConnected()
166 || getSocket().isOutputShutdown() || out == null ) {
167
168 fireResponseReceived(i18n.getMessage("DefaultLSConsoleModel.notConnected"));
169 } else {
170 CC.getTaskQueue().add(new LSConsoleExecCommand(cmd));
171 }
172
173 fireCommandExecuted();
174 }
175
176 /**
177 * Gets the last executed command.
178 * @return The last command executed in the LS Console.
179 */
180 @Override
181 public String
182 getLastExecutedCommand() {
183 int size = sessionHistory.size();
184 return size == 0 ? "" : sessionHistory.get(size - 1);
185 }
186
187 /**
188 * Sets the text in the command line.
189 * @param cmdLine The new command line text.
190 */
191 @Override
192 public void
193 setCommandLineText(String cmdLine) {
194 if(this.cmdLine.equals(cmdLine)) return;
195
196 String oldCmdLine = this.cmdLine;
197 this.cmdLine = cmdLine;
198 fireCommandLineTextChanged(oldCmdLine);
199 }
200
201 /**
202 * Gets the text in the command line.
203 * @return The command line's text.
204 */
205 @Override
206 public String
207 getCommandLineText() { return cmdLine; }
208
209 /**
210 * Gets the command history of the current session, including blank lines and comments.
211 * @return The command history of the current session, including blank lines and comments.
212 */
213 @Override
214 public String[]
215 getSessionHistory() {
216 return sessionHistory.toArray(new String[sessionHistory.size()]);
217 }
218
219 /**
220 * Clears the session history.
221 * @see #getSessionHistory
222 */
223 @Override
224 public void
225 clearSessionHistory() { sessionHistory.removeAllElements(); }
226
227 /**
228 * Adds the specified <code>command</code> to command history.
229 * @param command The command to be added to command history.
230 */
231 @Override
232 public void
233 addToCommandHistory(String command) { cmdHistory.add(command); }
234
235 /**
236 * Gets the complete command history, excluding blank lines and comments.
237 * @return The complete command history, excluding blank lines and comments.
238 */
239 @Override
240 public String[]
241 getCommandHistory() {
242 return cmdHistory.toArray(new String[cmdHistory.size()]);
243 }
244
245 /**
246 * Clears the complete/multisession command history.
247 * @see #getCommandHistory
248 */
249 @Override
250 public void
251 clearCommandHistory() {
252 cmdHistory.clear();
253 cmdHistoryIdx = -1;
254 }
255
256 /**
257 * Determines the maximum number of lines to be kept in the command history.
258 * @return The maximum number of lines to be kept in the command history.
259 */
260 @Override
261 public int
262 getCommandHistorySize() { return commandHistorySize; }
263
264 /**
265 * Sets the maximum number of lines to be kept in the command history.
266 * @param size Determines the maximum number of lines to be kept in the command history.
267 */
268 @Override
269 public void
270 setCommandHistorySize(int size) { commandHistorySize = size; }
271
272 /**
273 * Gets a list of all LSCP commands.
274 * @return A list of all LSCP commands.
275 */
276 @Override
277 public String[]
278 getCommandList() { return cmdList; }
279
280 /** Browses the command history one line up. */
281 @Override
282 public void
283 browseCommandHistoryUp() {
284 if(cmdHistory.size() == 0) return;
285
286 if(cmdHistoryIdx == -1) {
287 currentCmd = getCommandLineText();
288 cmdHistoryIdx = cmdHistory.size() - 1;
289 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
290 return;
291 }
292
293 if(cmdHistoryIdx == 0) return;
294
295 setCommandLineText(cmdHistory.get(--cmdHistoryIdx));
296 }
297
298 /** Browses the command history one line down. */
299 @Override
300 public void
301 browseCommandHistoryDown() {
302 if(cmdHistory.size() == 0 || cmdHistoryIdx == -1) return;
303 if(cmdHistoryIdx == cmdHistory.size() - 1) {
304 cmdHistoryIdx = -1;
305 setCommandLineText(currentCmd);
306 currentCmd = "";
307 return;
308 }
309
310 setCommandLineText(cmdHistory.get(++cmdHistoryIdx));
311 }
312
313 /** Browses to the first line of the command history. */
314 @Override
315 public void
316 browseCommandHistoryFirst() {
317 if(cmdHistory.size() == 0) return;
318 cmdHistoryIdx = 0;
319 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
320 }
321
322 /** Browses to the last line of the command history. */
323 @Override
324 public void
325 browseCommandHistoryLast() {
326 if(cmdHistory.size() == 0) return;
327 cmdHistoryIdx = cmdHistory.size() - 1;
328 setCommandLineText(cmdHistory.get(cmdHistoryIdx));
329 }
330
331 private Vector<String> tmpVector = new Vector<String>();
332
333 /**
334 * Searches the command history for commands
335 * containing the string returned by {@link #getCommandLineText}.
336 * @return All commands that contains the string returned by {@link #getCommandLineText}.
337 * @see #getCommandHistory
338 */
339 @Override
340 public String[]
341 searchCommandHistory() { return searchCommandHistory(getCommandLineText()); }
342
343 /**
344 * Searches the command history 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 @Override
350 public String[]
351 searchCommandHistory(String substring) {
352 tmpVector.removeAllElements();
353 for(String s : cmdHistory) if(s.indexOf(substring) != -1) tmpVector.add(s);
354
355 return tmpVector.toArray(new String[tmpVector.size()]);
356 }
357
358 /**
359 * Searches the LSCP command list for commands
360 * containing the string returned by {@link #getCommandLineText}.
361 * @return All commands that contains the string returned by {@link #getCommandLineText}.
362 * @see #getCommandList
363 */
364 @Override
365 public String[]
366 searchCommandList() { return searchCommandList(getCommandLineText()); }
367
368 /**
369 * Searches the LSCP command list for commands containing <code>substring</code>.
370 * @param substring The substring to be used to perform the search.
371 * @return All commands that contains <code>substring</code>.
372 * @see #getCommandList
373 */
374 @Override
375 public String[]
376 searchCommandList(String substring) {
377 tmpVector.removeAllElements();
378 for(String s : cmdList) if(s.indexOf(substring) != -1) tmpVector.add(s);
379
380 return tmpVector.toArray(new String[tmpVector.size()]);
381 }
382
383 /** Notifies listeners that the text in the command line has changed. */
384 private void
385 fireCommandLineTextChanged(String oldCmdLine) {
386 LSConsoleEvent e = new LSConsoleEvent(this, null, oldCmdLine);
387 for(LSConsoleListener l : listeners) l.commandLineTextChanged(e);
388 }
389
390 /** Notifies listeners that the command in the command line has been executed. */
391 private void
392 fireCommandExecuted() {
393 LSConsoleEvent e = new LSConsoleEvent(this);
394 for(LSConsoleListener l : listeners) l.commandExecuted(e);
395 }
396
397 /**
398 * Notifies listeners that response is received from LinuxSampler.
399 * @param response The response received from LinuxSampler.
400 */
401 private void
402 fireResponseReceived(final String response) {
403 SwingUtilities.invokeLater(new Runnable() {
404 public void
405 run() {
406 LSConsoleEvent e = new LSConsoleEvent(this, response);
407 for(LSConsoleListener l : listeners) l.responseReceived(e);
408 }
409 });
410 }
411
412 /** Executes LS Console command. */
413 private class LSConsoleExecCommand extends org.jsampler.task.EnhancedTask {
414 private String cmd;
415
416 /** Creates a new instance of <code>LSConsoleExecCommand</code>. */
417 public
418 LSConsoleExecCommand(String cmd) {
419 setTitle("LSConsoleExecCommand_task");
420 setDescription(i18n.getMessage("LSConsoleExecCommand.description"));
421 this.cmd = cmd;
422 }
423
424 /** The entry point of the task. */
425 public void
426 run() {
427 try { out.writeLine(cmd); }
428 catch(Exception x) {
429 setErrorMessage(getDescription() + ": " + HF.getErrorMessage(x));
430 CC.getLogger().log(Level.FINE, getErrorMessage(), x);
431 }
432 }
433 }
434
435 class LSConsoleThread extends Thread {
436 LscpInputStream in;
437 private boolean terminate = false;
438
439 LSConsoleThread() {super("LS-Console-Thread"); }
440
441 @Override
442 public void
443 run() {
444 while(!mustTerminate()) {
445 try { processInput(); }
446 catch(Exception x) {
447 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
448 }
449
450 try { synchronized(this) { wait(100); } }
451 catch(Exception x) {
452 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
453 }
454 }
455 }
456
457 private synchronized boolean
458 mustTerminate() { return terminate; }
459
460 public synchronized void
461 terminate() {
462 terminate = true;
463 this.notifyAll();
464 }
465
466 /** Processes the input sent by LinuxSampler */
467 private synchronized void
468 processInput() throws IOException {
469 while(in != null && in.available() > 0) {
470 String response = in.readLine();
471 fireResponseReceived(response);
472 }
473 }
474
475 public synchronized void
476 setInputStream(LscpInputStream in) { this.in = in; }
477 }
478
479 class LscpInputStream {
480 private InputStream in;
481 private StringBuffer buf = new StringBuffer();
482
483 /**
484 * Creates a new instance of LscpInputStream.
485 *
486 */
487 public
488 LscpInputStream(InputStream in) {
489 this.in = in;
490 }
491
492 /**
493 * Reads a line.
494 * This method is thread safe.
495 *
496 * @return A string containing the next line readed from the stream or
497 * <code>null</code> if the end of the stream has been reached.
498 * @throws IOException If an I/O error occurs.
499 */
500 public synchronized String
501 readLine() throws IOException {
502 int i;
503 buf.setLength(0);
504
505 while((i = in.read()) != -1) {
506 if(i == '\r') {
507 checkLF();
508 break;
509 }
510 buf.append((char)i);
511 }
512
513 if(i == -1) {
514 if(buf.length() > 0)
515 throw new IOException("Unexpected end of line!");
516 return null;
517 }
518 return buf.toString();
519 }
520
521 /**
522 * Returns the number of bytes that can
523 * be read from this input stream without blocking.
524 *
525 * @return The number of bytes that can
526 * be read from this input stream without blocking.
527 * @throws IOException If an I/O error occurs.
528 */
529 public synchronized int
530 available() throws IOException { return in.available(); }
531
532 private void
533 checkLF() throws IOException {
534 int i = in.read();
535 if(i == -1) throw new IOException("Unexpected end of file!");
536 if(i != '\n') throw new IOException("Unexpected end of line!");
537 }
538 }
539
540 class LscpOutputStream {
541 private OutputStream out;
542
543 /** Creates a new instance of LscpOutputStream */
544 public
545 LscpOutputStream(OutputStream out) { this.out = out; }
546
547 /*
548 * Writes a line.
549 * @param line a string to be written.
550 */
551 public void
552 writeLine(String line) throws IOException {
553 try {
554 out.write(line.getBytes("US-ASCII"));
555 out.write('\r');
556 out.write('\n');
557 out.flush();
558 } catch(UnsupportedEncodingException x) {
559 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
560 }
561 }
562 }
563 }

  ViewVC Help
Powered by ViewVC