Source Code Cross Referenced for Session.java in  » Net » Ganymed-SSH-2 » ch » ethz » ssh2 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » Ganymed SSH 2 » ch.ethz.ssh2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package ch.ethz.ssh2;
002:
003:        import java.io.IOException;
004:        import java.io.InputStream;
005:        import java.io.OutputStream;
006:        import java.security.SecureRandom;
007:
008:        import ch.ethz.ssh2.channel.Channel;
009:        import ch.ethz.ssh2.channel.ChannelManager;
010:        import ch.ethz.ssh2.channel.X11ServerData;
011:
012:        /**
013:         * A <code>Session</code> is a remote execution of a program. "Program" means
014:         * in this context either a shell, an application or a system command. The
015:         * program may or may not have a tty. Only one single program can be started on
016:         * a session. However, multiple sessions can be active simultaneously.
017:         * 
018:         * @author Christian Plattner, plattner@inf.ethz.ch
019:         * @version $Id: Session.java,v 1.9 2006/02/14 19:43:16 cplattne Exp $
020:         */
021:        public class Session {
022:            ChannelManager cm;
023:            Channel cn;
024:
025:            boolean flag_pty_requested = false;
026:            boolean flag_x11_requested = false;
027:            boolean flag_execution_started = false;
028:            boolean flag_closed = false;
029:
030:            String x11FakeCookie = null;
031:
032:            final SecureRandom rnd;
033:
034:            Session(ChannelManager cm, SecureRandom rnd) throws IOException {
035:                this .cm = cm;
036:                this .cn = cm.openSessionChannel();
037:                this .rnd = rnd;
038:            }
039:
040:            /**
041:             * Basically just a wrapper for lazy people - identical to calling
042:             * <code>requestPTY("dumb", 0, 0, 0, 0, null)</code>.
043:             * 
044:             * @throws IOException
045:             */
046:            public void requestDumbPTY() throws IOException {
047:                requestPTY("dumb", 0, 0, 0, 0, null);
048:            }
049:
050:            /**
051:             * Basically just another wrapper for lazy people - identical to calling
052:             * <code>requestPTY(term, 0, 0, 0, 0, null)</code>.
053:             * 
054:             * @throws IOException
055:             */
056:            public void requestPTY(String term) throws IOException {
057:                requestPTY(term, 0, 0, 0, 0, null);
058:            }
059:
060:            /**
061:             * Allocate a pseudo-terminal for this session.
062:             * <p>
063:             * This method may only be called before a program or shell is started in
064:             * this session.
065:             * <p>
066:             * Different aspects can be specified:
067:             * <p>
068:             * <ul>
069:             * <li>The TERM environment variable value (e.g., vt100)</li>
070:             * <li>The terminal's dimensions.</li>
071:             * <li>The encoded terminal modes.</li>
072:             * </ul>
073:             * Zero dimension parameters are ignored. The character/row dimensions
074:             * override the pixel dimensions (when nonzero). Pixel dimensions refer to
075:             * the drawable area of the window. The dimension parameters are only
076:             * informational. The encoding of terminal modes (parameter
077:             * <code>terminal_modes</code>) is described, e.g., in
078:             * draft-ietf-secsh-connect-XY.txt.
079:             * 
080:             * @param term
081:             *            The TERM environment variable value (e.g., vt100)
082:             * @param term_width_characters
083:             *            terminal width, characters (e.g., 80)
084:             * @param term_height_characters
085:             *            terminal height, rows (e.g., 24)
086:             * @param term_width_pixels
087:             *            terminal width, pixels (e.g., 640)
088:             * @param term_height_pixels
089:             *            terminal height, pixels (e.g., 480)
090:             * @param terminal_modes
091:             *            encoded terminal modes (may be <code>null</code>)
092:             * @throws IOException
093:             */
094:            public void requestPTY(String term, int term_width_characters,
095:                    int term_height_characters, int term_width_pixels,
096:                    int term_height_pixels, byte[] terminal_modes)
097:                    throws IOException {
098:                if (term == null)
099:                    throw new IllegalArgumentException("TERM cannot be null.");
100:
101:                if ((terminal_modes != null) && (terminal_modes.length > 0)) {
102:                    if (terminal_modes[terminal_modes.length - 1] != 0)
103:                        throw new IOException(
104:                                "Illegal terminal modes description, does not end in zero byte");
105:                } else
106:                    terminal_modes = new byte[] { 0 };
107:
108:                synchronized (this ) {
109:                    /* The following is just a nicer error, we would catch it anyway later in the channel code */
110:                    if (flag_closed)
111:                        throw new IOException("This session is closed.");
112:
113:                    if (flag_pty_requested)
114:                        throw new IOException("A PTY was already requested.");
115:
116:                    if (flag_execution_started)
117:                        throw new IOException(
118:                                "Cannot request PTY at this stage anymore, a remote execution has already started.");
119:
120:                    flag_pty_requested = true;
121:                }
122:
123:                cm.requestPTY(cn, term, term_width_characters,
124:                        term_height_characters, term_width_pixels,
125:                        term_height_pixels, terminal_modes);
126:            }
127:
128:            /**
129:             * Request X11 forwarding for the current session.
130:             * <p>
131:             * You have to supply the name and port of your X-server.
132:             * <p>
133:             * This method may only be called before a program or shell is started in
134:             * this session.
135:             * 
136:             * @param hostname the hostname of the real (target) X11 server (e.g., 127.0.0.1)
137:             * @param port the port of the real (target) X11 server (e.g., 6010)
138:             * @param cookie if non-null, then present this cookie to the real X11 server
139:             * @param singleConnection if true, then the server is instructed to only forward one single
140:             *        connection, no more connections shall be forwarded after first, or after the session
141:             *        channel has been closed
142:             * @throws IOException
143:             */
144:            public void requestX11Forwarding(String hostname, int port,
145:                    byte[] cookie, boolean singleConnection) throws IOException {
146:                if (hostname == null)
147:                    throw new IllegalArgumentException(
148:                            "hostname argument may not be null");
149:
150:                synchronized (this ) {
151:                    /* The following is just a nicer error, we would catch it anyway later in the channel code */
152:                    if (flag_closed)
153:                        throw new IOException("This session is closed.");
154:
155:                    if (flag_x11_requested)
156:                        throw new IOException(
157:                                "X11 forwarding was already requested.");
158:
159:                    if (flag_execution_started)
160:                        throw new IOException(
161:                                "Cannot request X11 forwarding at this stage anymore, a remote execution has already started.");
162:
163:                    flag_x11_requested = true;
164:                }
165:
166:                /* X11ServerData - used to store data about the target X11 server */
167:
168:                X11ServerData x11data = new X11ServerData();
169:
170:                x11data.hostname = hostname;
171:                x11data.port = port;
172:                x11data.x11_magic_cookie = cookie; /* if non-null, then present this cookie to the real X11 server */
173:
174:                /* Generate fake cookie - this one is used between remote clients and the ganymed proxy */
175:
176:                byte[] fakeCookie = new byte[16];
177:                String hexEncodedFakeCookie;
178:
179:                /* Make sure that this fake cookie is unique for this connection */
180:
181:                while (true) {
182:                    rnd.nextBytes(fakeCookie);
183:
184:                    /* Generate also hex representation of fake cookie */
185:
186:                    StringBuffer tmp = new StringBuffer(32);
187:                    for (int i = 0; i < fakeCookie.length; i++) {
188:                        String digit2 = Integer
189:                                .toHexString(fakeCookie[i] & 0xff);
190:                        tmp.append((digit2.length() == 2) ? digit2 : "0"
191:                                + digit2);
192:                    }
193:                    hexEncodedFakeCookie = tmp.toString();
194:
195:                    /* Well, yes, chances are low, but we want to be on the safe side */
196:
197:                    if (cm.checkX11Cookie(hexEncodedFakeCookie) == null)
198:                        break;
199:                }
200:
201:                /* Ask for X11 forwarding */
202:
203:                cm.requestX11(cn, singleConnection, "MIT-MAGIC-COOKIE-1",
204:                        hexEncodedFakeCookie, 0);
205:
206:                /* OK, that went fine, get ready to accept X11 connections... */
207:                /* ... but only if the user has not called close() in the meantime =) */
208:
209:                synchronized (this ) {
210:                    if (flag_closed == false) {
211:                        this .x11FakeCookie = hexEncodedFakeCookie;
212:                        cm.registerX11Cookie(hexEncodedFakeCookie, x11data);
213:                    }
214:                }
215:
216:                /* Now it is safe to start remote X11 programs */
217:            }
218:
219:            /**
220:             * Execute a command on the remote machine.
221:             * 
222:             * @param cmd
223:             *            The command to execute on the remote host.
224:             * @throws IOException
225:             */
226:            public void execCommand(String cmd) throws IOException {
227:                if (cmd == null)
228:                    throw new IllegalArgumentException(
229:                            "cmd argument may not be null");
230:
231:                synchronized (this ) {
232:                    /* The following is just a nicer error, we would catch it anyway later in the channel code */
233:                    if (flag_closed)
234:                        throw new IOException("This session is closed.");
235:
236:                    if (flag_execution_started)
237:                        throw new IOException(
238:                                "A remote execution has already started.");
239:
240:                    flag_execution_started = true;
241:                }
242:
243:                cm.requestExecCommand(cn, cmd);
244:            }
245:
246:            /**
247:             * Start a shell on the remote machine.
248:             * 
249:             * @throws IOException
250:             */
251:            public void startShell() throws IOException {
252:                synchronized (this ) {
253:                    /* The following is just a nicer error, we would catch it anyway later in the channel code */
254:                    if (flag_closed)
255:                        throw new IOException("This session is closed.");
256:
257:                    if (flag_execution_started)
258:                        throw new IOException(
259:                                "A remote execution has already started.");
260:
261:                    flag_execution_started = true;
262:                }
263:
264:                cm.requestShell(cn);
265:            }
266:
267:            /**
268:             * Start a subsystem on the remote machine.
269:             * Unless you know what you are doing, you will never need this.
270:             * 
271:             * @param name the name of the subsystem.
272:             * @throws IOException
273:             */
274:            public void startSubSystem(String name) throws IOException {
275:                if (name == null)
276:                    throw new IllegalArgumentException(
277:                            "name argument may not be null");
278:
279:                synchronized (this ) {
280:                    /* The following is just a nicer error, we would catch it anyway later in the channel code */
281:                    if (flag_closed)
282:                        throw new IOException("This session is closed.");
283:
284:                    if (flag_execution_started)
285:                        throw new IOException(
286:                                "A remote execution has already started.");
287:
288:                    flag_execution_started = true;
289:                }
290:
291:                cm.requestSubSystem(cn, name);
292:            }
293:
294:            public InputStream getStdout() {
295:                return cn.getStdoutStream();
296:            }
297:
298:            public InputStream getStderr() {
299:                return cn.getStderrStream();
300:            }
301:
302:            public OutputStream getStdin() {
303:                return cn.getStdinStream();
304:            }
305:
306:            /**
307:             * This method blocks until there is more data available on either the
308:             * stdout or stderr InputStream of this <code>Session</code>. Very useful
309:             * if you do not want to use two parallel threads for reading from the two
310:             * InputStreams. One can also specify a timeout. NOTE: do NOT call this
311:             * method if you use concurrent threads that operate on either of the two
312:             * InputStreams of this <code>Session</code> (otherwise this method may
313:             * block, even though more data is available).
314:             * 
315:             * @param timeout
316:             *            The (non-negative) timeout in <code>ms</code>. <code>0</code> means no
317:             *            timeout, the call may block forever.
318:             * @return
319:             *            <ul>
320:             *            <li><code>0</code> if no more data will arrive.</li>
321:             *            <li><code>1</code> if more data is available.</li>
322:             *            <li><code>-1</code> if a timeout occurred.</li>
323:             *            </ul>
324:             *            
325:             * @throws    IOException
326:             * @deprecated This method has been replaced with a much more powerful wait-for-condition
327:             *             interface and therefore acts only as a wrapper.
328:             * 
329:             */
330:            public int waitUntilDataAvailable(long timeout) throws IOException {
331:                if (timeout < 0)
332:                    throw new IllegalArgumentException(
333:                            "timeout must not be negative!");
334:
335:                int conditions = cm.waitForCondition(cn, timeout,
336:                        ChannelCondition.STDOUT_DATA
337:                                | ChannelCondition.STDERR_DATA
338:                                | ChannelCondition.EOF);
339:
340:                if ((conditions & ChannelCondition.TIMEOUT) != 0)
341:                    return -1;
342:
343:                if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) != 0)
344:                    return 1;
345:
346:                /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */
347:
348:                if ((conditions & ChannelCondition.EOF) != 0)
349:                    return 0;
350:
351:                throw new IllegalStateException("Unexpected condition result ("
352:                        + conditions + ")");
353:            }
354:
355:            /**
356:             * This method blocks until certain conditions hold true on the underlying SSH-2 channel.
357:             * <p>
358:             * This method returns as soon as one of the following happens:
359:             * <ul>
360:             * <li>at least of the specified conditions (see {@link ChannelCondition}) holds true</li>
361:             * <li>timeout > 0 and a timeout occured (TIMEOUT will be set in result conditions)</a> 
362:             * <li>the underlying channel was closed (CLOSED will be set in result conditions)</a>
363:             * </ul>
364:             * <p>
365:             * In any case, the result value contains ALL current conditions, which may be more
366:             * than the specified condition set (i.e., never use the "==" operator to test for conditions
367:             * in the bitmask, see also comments in {@link ChannelCondition}). 
368:             * <p>
369:             * Note: do NOT call this method if you want to wait for STDOUT_DATA or STDERR_DATA and
370:             * there are concurrent threads (e.g., StreamGobblers) that operate on either of the two
371:             * InputStreams of this <code>Session</code> (otherwise this method may
372:             * block, even though more data is available in the StreamGobblers).
373:             * 
374:             * @param condition_set a bitmask based on {@link ChannelCondition} values
375:             * @param timeout non-negative timeout in ms, <code>0</code> means no timeout
376:             * @return all bitmask specifying all current conditions that are true
377:             */
378:
379:            public int waitForCondition(int condition_set, long timeout) {
380:                if (timeout < 0)
381:                    throw new IllegalArgumentException(
382:                            "timeout must be non-negative!");
383:
384:                return cm.waitForCondition(cn, timeout, condition_set);
385:            }
386:
387:            /**
388:             * Get the exit code/status from the remote command - if available. Be
389:             * careful - not all server implementations return this value. It is
390:             * generally a good idea to call this method only when all data from the
391:             * remote side has been consumed (see also the <code<WaitForCondition</code> method).
392:             * 
393:             * @return An <code>Integer</code> holding the exit code, or
394:             *         <code>null</code> if no exit code is (yet) available.
395:             */
396:            public Integer getExitStatus() {
397:                return cn.getExitStatus();
398:            }
399:
400:            /**
401:             * Get the name of the signal by which the process on the remote side was
402:             * stopped - if available and applicable. Be careful - not all server
403:             * implementations return this value.
404:             * 
405:             * @return An <code>String</code> holding the name of the signal, or
406:             *         <code>null</code> if the process exited normally or is still
407:             *         running (or if the server forgot to send this information).
408:             */
409:            public String getExitSignal() {
410:                return cn.getExitSignal();
411:            }
412:
413:            /**
414:             * Close this session. NEVER forget to call this method to free up resources -
415:             * even if you got an exception from one of the other methods (or when
416:             * getting an Exception on the Input- or OutputStreams). Sometimes these other
417:             * methods may throw an exception, saying that the underlying channel is
418:             * closed (this can happen, e.g., if the other server sent a close message.)
419:             * However, as long as you have not called the <code>close()</code>
420:             * method, you may be wasting (local) resources.
421:             * 
422:             */
423:            public void close() {
424:                synchronized (this ) {
425:                    if (flag_closed)
426:                        return;
427:
428:                    flag_closed = true;
429:
430:                    if (x11FakeCookie != null)
431:                        cm.unRegisterX11Cookie(x11FakeCookie, true);
432:
433:                    try {
434:                        cm.closeChannel(cn, "Closed due to user request", true);
435:                    } catch (IOException ignored) {
436:                    }
437:                }
438:            }
439:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.