001: /*
002: * Copyright 2003-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.net.telnet;
017:
018: import java.io.BufferedInputStream;
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import org.apache.commons.net.io.FromNetASCIIInputStream;
023: import org.apache.commons.net.io.ToNetASCIIOutputStream;
024:
025: /***
026: * The TelnetClient class implements the simple network virtual
027: * terminal (NVT) for the Telnet protocol according to RFC 854. It
028: * does not implement any of the extra Telnet options because it
029: * is meant to be used within a Java program providing automated
030: * access to Telnet accessible resources.
031: * <p>
032: * The class can be used by first connecting to a server using the
033: * SocketClient
034: * {@link org.apache.commons.net.SocketClient#connect connect}
035: * method. Then an InputStream and OutputStream for sending and
036: * receiving data over the Telnet connection can be obtained by
037: * using the {@link #getInputStream getInputStream() } and
038: * {@link #getOutputStream getOutputStream() } methods.
039: * When you finish using the streams, you must call
040: * {@link #disconnect disconnect } rather than simply
041: * closing the streams.
042: * <p>
043: * <p>
044: * @author Daniel F. Savarese
045: * @author Bruno D'Avanzo
046: ***/
047:
048: public class TelnetClient extends Telnet {
049: private InputStream __input;
050: private OutputStream __output;
051: protected boolean readerThread = true;
052:
053: /***
054: * Default TelnetClient constructor.
055: ***/
056: public TelnetClient() {
057: /* TERMINAL-TYPE option (start)*/
058: super ("VT100");
059: /* TERMINAL-TYPE option (end)*/
060: __input = null;
061: __output = null;
062: }
063:
064: /* TERMINAL-TYPE option (start)*/
065: public TelnetClient(String termtype) {
066: super (termtype);
067: __input = null;
068: __output = null;
069: }
070:
071: /* TERMINAL-TYPE option (end)*/
072:
073: void _flushOutputStream() throws IOException {
074: _output_.flush();
075: }
076:
077: void _closeOutputStream() throws IOException {
078: _output_.close();
079: }
080:
081: /***
082: * Handles special connection requirements.
083: * <p>
084: * @exception IOException If an error occurs during connection setup.
085: ***/
086: protected void _connectAction_() throws IOException {
087: super ._connectAction_();
088: InputStream input;
089: TelnetInputStream tmp;
090:
091: if (FromNetASCIIInputStream.isConversionRequired())
092: input = new FromNetASCIIInputStream(_input_);
093: else
094: input = _input_;
095:
096: tmp = new TelnetInputStream(input, this , readerThread);
097: if (readerThread) {
098: tmp._start();
099: }
100: // __input CANNOT refer to the TelnetInputStream. We run into
101: // blocking problems when some classes use TelnetInputStream, so
102: // we wrap it with a BufferedInputStream which we know is safe.
103: // This blocking behavior requires further investigation, but right
104: // now it looks like classes like InputStreamReader are not implemented
105: // in a safe manner.
106: __input = new BufferedInputStream(tmp);
107: __output = new ToNetASCIIOutputStream(new TelnetOutputStream(
108: this ));
109: }
110:
111: /***
112: * Disconnects the telnet session, closing the input and output streams
113: * as well as the socket. If you have references to the
114: * input and output streams of the telnet connection, you should not
115: * close them yourself, but rather call disconnect to properly close
116: * the connection.
117: ***/
118: public void disconnect() throws IOException {
119: __input.close();
120: __output.close();
121: super .disconnect();
122: }
123:
124: /***
125: * Returns the telnet connection output stream. You should not close the
126: * stream when you finish with it. Rather, you should call
127: * {@link #disconnect disconnect }.
128: * <p>
129: * @return The telnet connection output stream.
130: ***/
131: public OutputStream getOutputStream() {
132: return __output;
133: }
134:
135: /***
136: * Returns the telnet connection input stream. You should not close the
137: * stream when you finish with it. Rather, you should call
138: * {@link #disconnect disconnect }.
139: * <p>
140: * @return The telnet connection input stream.
141: ***/
142: public InputStream getInputStream() {
143: return __input;
144: }
145:
146: /***
147: * Returns the state of the option on the local side.
148: * <p>
149: * @param option - Option to be checked.
150: * <p>
151: * @return The state of the option on the local side.
152: ***/
153: public boolean getLocalOptionState(int option) {
154: /* BUG (option active when not already acknowledged) (start)*/
155: return (_stateIsWill(option) && _requestedWill(option));
156: /* BUG (option active when not already acknowledged) (end)*/
157: }
158:
159: /***
160: * Returns the state of the option on the remote side.
161: * <p>
162: * @param option - Option to be checked.
163: * <p>
164: * @return The state of the option on the remote side.
165: ***/
166: public boolean getRemoteOptionState(int option) {
167: /* BUG (option active when not already acknowledged) (start)*/
168: return (_stateIsDo(option) && _requestedDo(option));
169: /* BUG (option active when not already acknowledged) (end)*/
170: }
171:
172: /* open TelnetOptionHandler functionality (end)*/
173:
174: /* Code Section added for supporting AYT (start)*/
175:
176: /***
177: * Sends an Are You There sequence and waits for the result.
178: * <p>
179: * @throws InterruptedException
180: * @throws IllegalArgumentException
181: * @throws IOException
182: * <p>
183: * @param timeout - Time to wait for a response (millis.)
184: * <p>
185: * @return true if AYT received a response, false otherwise
186: ***/
187: public boolean sendAYT(long timeout) throws IOException,
188: IllegalArgumentException, InterruptedException {
189: return (_sendAYT(timeout));
190: }
191:
192: /* Code Section added for supporting AYT (start)*/
193:
194: /* open TelnetOptionHandler functionality (start)*/
195:
196: /***
197: * Registers a new TelnetOptionHandler for this telnet client to use.
198: * <p>
199: * @throws InvalidTelnetOptionException
200: * <p>
201: * @param opthand - option handler to be registered.
202: ***/
203: public void addOptionHandler(TelnetOptionHandler opthand)
204: throws InvalidTelnetOptionException {
205: super .addOptionHandler(opthand);
206: }
207:
208: /* open TelnetOptionHandler functionality (end)*/
209:
210: /***
211: * Unregisters a TelnetOptionHandler.
212: * <p>
213: * @throws InvalidTelnetOptionException
214: * <p>
215: * @param optcode - Code of the option to be unregistered.
216: ***/
217: public void deleteOptionHandler(int optcode)
218: throws InvalidTelnetOptionException {
219: super .deleteOptionHandler(optcode);
220: }
221:
222: /* Code Section added for supporting spystreams (start)*/
223: /***
224: * Registers an OutputStream for spying what's going on in
225: * the TelnetClient session.
226: * <p>
227: * @param spystream - OutputStream on which session activity
228: * will be echoed.
229: ***/
230: public void registerSpyStream(OutputStream spystream) {
231: super ._registerSpyStream(spystream);
232: }
233:
234: /***
235: * Stops spying this TelnetClient.
236: * <p>
237: ***/
238: public void stopSpyStream() {
239: super ._stopSpyStream();
240: }
241:
242: /* Code Section added for supporting spystreams (end)*/
243:
244: /***
245: * Registers a notification handler to which will be sent
246: * notifications of received telnet option negotiation commands.
247: * <p>
248: * @param notifhand - TelnetNotificationHandler to be registered
249: ***/
250: public void registerNotifHandler(TelnetNotificationHandler notifhand) {
251: super .registerNotifHandler(notifhand);
252: }
253:
254: /***
255: * Unregisters the current notification handler.
256: * <p>
257: ***/
258: public void unregisterNotifHandler() {
259: super .unregisterNotifHandler();
260: }
261:
262: /***
263: * Sets the status of the reader thread.
264: * The reader thread status will apply to all subsequent connections
265: * <p>
266: * @param flag - true switches the reader thread on, false switches it off
267: ***/
268: public void setReaderThread(boolean flag) {
269: readerThread = flag;
270: }
271:
272: /***
273: * Gets the status of the reader thread.
274: * <p>
275: * @return true if the reader thread is on, false otherwise
276: ***/
277: public boolean getReaderThread() {
278: return (readerThread);
279: }
280: }
|