View Javadoc

1   /*
2    * Copyright 2003-2004 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.net.telnet;
17  
18  import java.io.BufferedInputStream;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  import org.apache.commons.net.io.FromNetASCIIInputStream;
23  import org.apache.commons.net.io.ToNetASCIIOutputStream;
24  
25  /***
26   * The TelnetClient class implements the simple network virtual
27   * terminal (NVT) for the Telnet protocol according to RFC 854.  It
28   * does not implement any of the extra Telnet options because it
29   * is meant to be used within a Java program providing automated
30   * access to Telnet accessible resources.
31   * <p>
32   * The class can be used by first connecting to a server using the
33   * SocketClient
34   * {@link org.apache.commons.net.SocketClient#connect connect}
35   * method.  Then an InputStream and OutputStream for sending and
36   * receiving data over the Telnet connection can be obtained by
37   * using the {@link #getInputStream  getInputStream() } and
38   * {@link #getOutputStream  getOutputStream() } methods.
39   * When you finish using the streams, you must call
40   * {@link #disconnect  disconnect } rather than simply
41   * closing the streams.
42   * <p>
43   * <p>
44   * @author Daniel F. Savarese
45   * @author Bruno D'Avanzo
46   ***/
47  
48  public class TelnetClient extends Telnet
49  {
50      private InputStream __input;
51      private OutputStream __output;
52      protected boolean readerThread = true;
53  
54      /***
55       * Default TelnetClient constructor.
56       ***/
57      public TelnetClient()
58      {
59          /* TERMINAL-TYPE option (start)*/
60          super ("VT100");
61          /* TERMINAL-TYPE option (end)*/
62          __input = null;
63          __output = null;
64      }
65  
66      /* TERMINAL-TYPE option (start)*/
67      public TelnetClient(String termtype)
68      {
69          super (termtype);
70          __input = null;
71          __output = null;
72      }
73      /* TERMINAL-TYPE option (end)*/
74  
75      void _flushOutputStream() throws IOException
76      {
77          _output_.flush();
78      }
79      void _closeOutputStream() throws IOException
80      {
81          _output_.close();
82      }
83  
84      /***
85       * Handles special connection requirements.
86       * <p>
87       * @exception IOException  If an error occurs during connection setup.
88       ***/
89      protected void _connectAction_() throws IOException
90      {
91          super._connectAction_();
92          InputStream input;
93          TelnetInputStream tmp;
94  
95          if (FromNetASCIIInputStream.isConversionRequired())
96              input = new FromNetASCIIInputStream(_input_);
97          else
98              input = _input_;
99  
100 
101         tmp = new TelnetInputStream(input, this, readerThread);
102         if(readerThread)
103         {
104             tmp._start();
105         }
106         // __input CANNOT refer to the TelnetInputStream.  We run into
107         // blocking problems when some classes use TelnetInputStream, so
108         // we wrap it with a BufferedInputStream which we know is safe.
109         // This blocking behavior requires further investigation, but right
110         // now it looks like classes like InputStreamReader are not implemented
111         // in a safe manner.
112         __input = new BufferedInputStream(tmp);
113         __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this));
114     }
115 
116     /***
117      * Disconnects the telnet session, closing the input and output streams
118      * as well as the socket.  If you have references to the
119      * input and output streams of the telnet connection, you should not
120      * close them yourself, but rather call disconnect to properly close
121      * the connection.
122      ***/
123     public void disconnect() throws IOException
124     {
125         __input.close();
126         __output.close();
127         super.disconnect();
128     }
129 
130     /***
131      * Returns the telnet connection output stream.  You should not close the
132      * stream when you finish with it.  Rather, you should call
133      * {@link #disconnect  disconnect }.
134      * <p>
135      * @return The telnet connection output stream.
136      ***/
137     public OutputStream getOutputStream()
138     {
139         return __output;
140     }
141 
142     /***
143      * Returns the telnet connection input stream.  You should not close the
144      * stream when you finish with it.  Rather, you should call
145      * {@link #disconnect  disconnect }.
146      * <p>
147      * @return The telnet connection input stream.
148      ***/
149     public InputStream getInputStream()
150     {
151         return __input;
152     }
153 
154     /***
155      * Returns the state of the option on the local side.
156      * <p>
157      * @param option - Option to be checked.
158      * <p>
159      * @return The state of the option on the local side.
160      ***/
161     public boolean getLocalOptionState(int option)
162     {
163         /* BUG (option active when not already acknowledged) (start)*/
164         return (_stateIsWill(option) && _requestedWill(option));
165         /* BUG (option active when not already acknowledged) (end)*/
166     }
167 
168     /***
169      * Returns the state of the option on the remote side.
170      * <p>
171      * @param option - Option to be checked.
172      * <p>
173      * @return The state of the option on the remote side.
174      ***/
175     public boolean getRemoteOptionState(int option)
176     {
177         /* BUG (option active when not already acknowledged) (start)*/
178         return (_stateIsDo(option) && _requestedDo(option));
179         /* BUG (option active when not already acknowledged) (end)*/
180     }
181     /* open TelnetOptionHandler functionality (end)*/
182 
183     /* Code Section added for supporting AYT (start)*/
184 
185     /***
186      * Sends an Are You There sequence and waits for the result.
187      * <p>
188      * @throws InterruptedException
189      * @throws IllegalArgumentException
190      * @throws IOException
191      * <p>
192      * @param timeout - Time to wait for a response (millis.)
193      * <p>
194      * @return true if AYT received a response, false otherwise
195      ***/
196     public boolean sendAYT(long timeout)
197     throws IOException, IllegalArgumentException, InterruptedException
198     {
199         return (_sendAYT(timeout));
200     }
201     /* Code Section added for supporting AYT (start)*/
202 
203     /* open TelnetOptionHandler functionality (start)*/
204 
205     /***
206      * Registers a new TelnetOptionHandler for this telnet client to use.
207      * <p>
208      * @throws InvalidTelnetOptionException
209      * <p>
210      * @param opthand - option handler to be registered.
211      ***/
212     public void addOptionHandler(TelnetOptionHandler opthand)
213     throws InvalidTelnetOptionException
214     {
215         super.addOptionHandler(opthand);
216     }
217     /* open TelnetOptionHandler functionality (end)*/
218 
219     /***
220      * Unregisters a  TelnetOptionHandler.
221      * <p>
222      * @throws InvalidTelnetOptionException
223      * <p>
224      * @param optcode - Code of the option to be unregistered.
225      ***/
226     public void deleteOptionHandler(int optcode)
227     throws InvalidTelnetOptionException
228     {
229         super.deleteOptionHandler(optcode);
230     }
231 
232     /* Code Section added for supporting spystreams (start)*/
233     /***
234      * Registers an OutputStream for spying what's going on in
235      * the TelnetClient session.
236      * <p>
237      * @param spystream - OutputStream on which session activity
238      * will be echoed.
239      ***/
240     public void registerSpyStream(OutputStream  spystream)
241     {
242         super._registerSpyStream(spystream);
243     }
244 
245     /***
246      * Stops spying this TelnetClient.
247      * <p>
248      ***/
249     public void stopSpyStream()
250     {
251         super._stopSpyStream();
252     }
253     /* Code Section added for supporting spystreams (end)*/
254 
255     /***
256      * Registers a notification handler to which will be sent
257      * notifications of received telnet option negotiation commands.
258      * <p>
259      * @param notifhand - TelnetNotificationHandler to be registered
260      ***/
261     public void registerNotifHandler(TelnetNotificationHandler  notifhand)
262     {
263         super.registerNotifHandler(notifhand);
264     }
265 
266     /***
267      * Unregisters the current notification handler.
268      * <p>
269      ***/
270     public void unregisterNotifHandler()
271     {
272         super.unregisterNotifHandler();
273     }
274 
275     /***
276      * Sets the status of the reader thread.
277      * The reader thread status will apply to all subsequent connections
278      * <p>
279      * @param flag - true switches the reader thread on, false switches it off
280      ***/
281     public void setReaderThread(boolean flag)
282     {
283         readerThread = flag;
284     }
285 
286     /***
287      * Gets the status of the reader thread.
288      * <p>
289      * @return true if the reader thread is on, false otherwise
290      ***/
291     public boolean getReaderThread()
292     {
293         return (readerThread);
294     }
295 }