001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.j2ssh.io;
027:
028: import com.sshtools.j2ssh.*;
029:
030: import org.apache.commons.logging.*;
031:
032: import java.io.*;
033:
034: import javax.swing.event.*;
035:
036: /**
037: *
038: *
039: * @author $author$
040: * @version $Revision: 1.29 $
041: */
042: public class IOStreamConnector {
043: private static Log log = LogFactory.getLog(IOStreamConnector.class);
044: private IOStreamConnectorState state = new IOStreamConnectorState();
045: private InputStream in = null;
046: private OutputStream out = null;
047: private Thread thread;
048: private long bytes;
049: private boolean closeInput = true;
050: private boolean closeOutput = true;
051:
052: /** */
053: protected EventListenerList listenerList = new EventListenerList();
054:
055: /**
056: * Creates a new IOStreamConnector object.
057: */
058: public IOStreamConnector() {
059: }
060:
061: /**
062: * Creates a new IOStreamConnector object.
063: *
064: * @param in
065: * @param out
066: */
067: public IOStreamConnector(InputStream in, OutputStream out) {
068: connect(in, out);
069: }
070:
071: /**
072: *
073: *
074: * @return
075: */
076: public IOStreamConnectorState getState() {
077: return state;
078: }
079:
080: /**
081: *
082: *
083: * @throws IOException
084: */
085: public void close() throws IOException {
086: log.info("Closing IOStreamConnector");
087: state.setValue(IOStreamConnectorState.CLOSED);
088:
089: if (closeInput) {
090: in.close();
091: }
092:
093: if (closeOutput) {
094: out.close();
095: }
096:
097: thread = null;
098: }
099:
100: /**
101: *
102: *
103: * @param closeInput
104: */
105: public void setCloseInput(boolean closeInput) {
106: this .closeInput = closeInput;
107: }
108:
109: /**
110: *
111: *
112: * @param closeOutput
113: */
114: public void setCloseOutput(boolean closeOutput) {
115: this .closeOutput = closeOutput;
116: }
117:
118: /**
119: *
120: *
121: * @param in
122: * @param out
123: */
124: public void connect(InputStream in, OutputStream out) {
125: this .in = in;
126: this .out = out;
127: log.info("Connecting InputStream to OutputStream");
128: state.setValue(IOStreamConnectorState.CONNECTED);
129: thread = new SshThread(new IOStreamConnectorThread(),
130: "IOStream connector", true);
131: thread.start();
132: }
133:
134: /**
135: *
136: *
137: * @return
138: */
139: public long getBytes() {
140: return bytes;
141: }
142:
143: /**
144: *
145: *
146: * @param l
147: */
148: public void addIOStreamConnectorListener(IOStreamConnectorListener l) {
149: listenerList.add(IOStreamConnectorListener.class, l);
150: }
151:
152: /**
153: *
154: *
155: * @param l
156: */
157: public void removeIOStreamConnectorListener(
158: IOStreamConnectorListener l) {
159: listenerList.remove(IOStreamConnectorListener.class, l);
160: }
161:
162: class IOStreamConnectorThread implements Runnable {
163: private Log log = LogFactory
164: .getLog(IOStreamConnectorThread.class);
165:
166: public void run() {
167: byte[] buffer = new byte[4096];
168: int read = 0;
169: int count;
170: int available;
171: log.info("Starting IOStreamConnectorThread thread");
172:
173: while (state.getValue() == IOStreamConnectorState.CONNECTED) {
174: try {
175: // Block
176: read = in.read(buffer, 0, 1);
177:
178: if (read > 0) {
179: count = read;
180: available = in.available();
181:
182: // Verify the buffer length and adjust if necersary
183: if ((available > 0)
184: && ((buffer.length - 1) < available)) {
185: byte[] tmp = new byte[available + 1];
186: System.arraycopy(buffer, 0, tmp, 0, 1);
187: buffer = tmp;
188: }
189:
190: // Read the remaining available bytes of the message
191: if (available > 0) {
192: read = in.read(buffer, 1, available);
193: count += read;
194: }
195:
196: // Write the message to the output stream
197: out.write(buffer, 0, count);
198: bytes += count;
199:
200: // Flush it
201: out.flush();
202:
203: // Inform all of the listeners
204: IOStreamConnectorListener[] l = (IOStreamConnectorListener[]) listenerList
205: .getListeners(IOStreamConnectorListener.class);
206:
207: for (int i = (l.length - 1); i >= 0; i--) {
208: l[i].data(buffer, count);
209: }
210: } else {
211: log.debug("Blocking read returned with "
212: + String.valueOf(read));
213:
214: if (read < 0) {
215: state.setValue(IOStreamConnectorState.EOF);
216: }
217: }
218: } catch (IOException ioe) {
219: // only warn if were supposed to be still connected, as we will ignore close exceptions
220: if (state.getValue() == IOStreamConnectorState.CONNECTED) {
221: log.debug(ioe.getMessage());
222: state.setValue(IOStreamConnectorState.EOF);
223: }
224: }
225: }
226:
227: try {
228: // if were not already closed then close the connector
229: if (state.getValue() != IOStreamConnectorState.CLOSED) {
230: close();
231: }
232: } catch (IOException ioe) {
233: }
234:
235: log.info("IOStreamConnectorThread is exiting");
236: }
237: }
238: }
|