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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1867 - (hide annotations) (download)
Mon Mar 16 22:12:32 2009 UTC (15 years, 1 month ago) by iliev
File size: 14779 byte(s)
* proper handling of connection failures
* renamed Channels Panels to Channel Lanes
* code cleanup

1 iliev 913 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1786 * Copyright (C) 2005-2008 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 913 *
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 iliev 1786 public void
118     disconnect() {
119     try { if(getSocket() != null) getSocket().close(); }
120     catch(Exception x) { CC.getLogger().info(HF.getErrorMessage(x)); }
121     }
122    
123 iliev 913 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 iliev 1786 @Override
141 iliev 913 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 iliev 1786 @Override
149 iliev 913 public void
150     removeLSConsoleListener(LSConsoleListener l) { listeners.remove(l); }
151    
152     /** Executes the command specified in the command line. */
153 iliev 1786 @Override
154 iliev 913 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 iliev 1786 @Override
181 iliev 913 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 iliev 1786 @Override
192 iliev 913 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 iliev 1786 @Override
206 iliev 913 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 iliev 1786 @Override
214 iliev 913 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 iliev 1786 @Override
224 iliev 913 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 iliev 1786 @Override
232 iliev 913 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 iliev 1786 @Override
240 iliev 913 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 iliev 1786 @Override
250 iliev 913 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 iliev 1786 @Override
261 iliev 913 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 iliev 1786 @Override
269 iliev 913 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 iliev 1786 @Override
277 iliev 913 public String[]
278     getCommandList() { return cmdList; }
279    
280     /** Browses the command history one line up. */
281 iliev 1786 @Override
282 iliev 913 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 iliev 1786 @Override
300 iliev 913 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 iliev 1786 @Override
315 iliev 913 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 iliev 1786 @Override
324 iliev 913 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 iliev 1786 @Override
340 iliev 913 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 iliev 1786 @Override
350 iliev 913 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 iliev 1786 @Override
365 iliev 913 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 iliev 1786 @Override
375 iliev 913 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 iliev 1867 exec() throws Exception { out.writeLine(cmd); }
427 iliev 913 }
428    
429     class LSConsoleThread extends Thread {
430     LscpInputStream in;
431     private boolean terminate = false;
432    
433     LSConsoleThread() {super("LS-Console-Thread"); }
434    
435 iliev 1786 @Override
436 iliev 913 public void
437     run() {
438     while(!mustTerminate()) {
439     try { processInput(); }
440     catch(Exception x) {
441     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
442     }
443    
444     try { synchronized(this) { wait(100); } }
445     catch(Exception x) {
446     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
447     }
448     }
449     }
450    
451     private synchronized boolean
452     mustTerminate() { return terminate; }
453    
454     public synchronized void
455     terminate() {
456     terminate = true;
457     this.notifyAll();
458     }
459    
460     /** Processes the input sent by LinuxSampler */
461     private synchronized void
462     processInput() throws IOException {
463     while(in != null && in.available() > 0) {
464     String response = in.readLine();
465     fireResponseReceived(response);
466     }
467     }
468    
469     public synchronized void
470     setInputStream(LscpInputStream in) { this.in = in; }
471     }
472    
473     class LscpInputStream {
474     private InputStream in;
475     private StringBuffer buf = new StringBuffer();
476    
477     /**
478     * Creates a new instance of LscpInputStream.
479     *
480     */
481     public
482     LscpInputStream(InputStream in) {
483     this.in = in;
484     }
485    
486     /**
487     * Reads a line.
488     * This method is thread safe.
489     *
490     * @return A string containing the next line readed from the stream or
491     * <code>null</code> if the end of the stream has been reached.
492     * @throws IOException If an I/O error occurs.
493     */
494     public synchronized String
495     readLine() throws IOException {
496     int i;
497     buf.setLength(0);
498    
499     while((i = in.read()) != -1) {
500     if(i == '\r') {
501     checkLF();
502     break;
503     }
504     buf.append((char)i);
505     }
506    
507     if(i == -1) {
508     if(buf.length() > 0)
509     throw new IOException("Unexpected end of line!");
510     return null;
511     }
512     return buf.toString();
513     }
514    
515     /**
516     * Returns the number of bytes that can
517     * be read from this input stream without blocking.
518     *
519     * @return The number of bytes that can
520     * be read from this input stream without blocking.
521     * @throws IOException If an I/O error occurs.
522     */
523     public synchronized int
524     available() throws IOException { return in.available(); }
525    
526     private void
527     checkLF() throws IOException {
528     int i = in.read();
529     if(i == -1) throw new IOException("Unexpected end of file!");
530     if(i != '\n') throw new IOException("Unexpected end of line!");
531     }
532     }
533    
534     class LscpOutputStream {
535     private OutputStream out;
536    
537     /** Creates a new instance of LscpOutputStream */
538     public
539     LscpOutputStream(OutputStream out) { this.out = out; }
540    
541     /*
542     * Writes a line.
543     * @param line a string to be written.
544     */
545     public void
546     writeLine(String line) throws IOException {
547     try {
548     out.write(line.getBytes("US-ASCII"));
549     out.write('\r');
550     out.write('\n');
551     out.flush();
552     } catch(UnsupportedEncodingException x) {
553     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
554     }
555     }
556     }
557     }

  ViewVC Help
Powered by ViewVC