package dmg.util;
import javatunnel.TunnelSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.Channels;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
public class DummyStreamEngine implements StreamEngine
{
private static final Logger _logger =
LoggerFactory.getLogger(DummyStreamEngine.class);
private final Socket _socket;
private Subject _subject = new Subject();
private ByteChannel _channel;
private OutputStream _outputStream;
private InputStream _inputStream;
private Reader _reader;
private Writer _writer;
public DummyStreamEngine(Socket socket) throws IOException
{
_socket = socket;
if (socket instanceof TunnelSocket) {
if (!((TunnelSocket) socket).verify()) {
String hostAddress = (socket.getInetAddress()).getHostAddress();
socket.close();
throw new IOException("Host " + hostAddress + ": Tunnel verification failed!");
}
setSubject(((TunnelSocket) socket).getSubject());
}
SocketChannel channel = _socket.getChannel();
if (channel != null) {
_channel = wrapChannel(channel);
}
}
public void setSubject(Subject subject)
{
_subject = subject;
}
@Override
public Subject getSubject()
{
return _subject;
}
@Override
public InetAddress getInetAddress()
{
return _socket.getInetAddress();
}
@Override
public synchronized InputStream getInputStream()
{
if (_inputStream == null) {
if (_channel == null) {
try {
_inputStream = _socket.getInputStream();
} catch (IOException e) {
_logger.error("Could not create input stream: " + e.getMessage());
}
} else {
_inputStream = Channels.newInputStream(_channel);
}
}
return _inputStream;
}
@Override
public synchronized OutputStream getOutputStream()
{
if (_outputStream == null) {
if (_channel == null) {
try {
_outputStream = _socket.getOutputStream();
} catch (IOException e) {
_logger.error("Could not create output stream: " + e.getMessage());
}
} else {
_outputStream = Channels.newOutputStream(_channel);
}
}
return _outputStream;
}
@Override
public synchronized Reader getReader()
{
if (_reader == null) {
if (_channel == null) {
_reader = new InputStreamReader(getInputStream());
} else {
_reader = Channels.
newReader(_channel, Charset.defaultCharset().newDecoder(), -1);
}
}
return _reader;
}
@Override
public synchronized Writer getWriter()
{
if (_writer == null) {
if (_channel == null) {
_writer = new OutputStreamWriter(getOutputStream());
} else {
_writer = Channels.
newWriter(_channel, Charset.defaultCharset().newEncoder(), -1);
}
}
return _writer;
}
@Override
public Socket getSocket()
{
return _socket;
}
@Override
public InetAddress getLocalAddress()
{
return _socket.getLocalAddress();
}
@Override
public String getTerminalType()
{
return "dumb";
}
@Override
public int getTerminalWidth()
{
return 0;
}
@Override
public int getTerminalHeight()
{
return 0;
}
/**
* Workaround for Java bug
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4509080. The
* workaround was taken from
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4774871.
*/
private static ByteChannel wrapChannel(final ByteChannel channel)
{
return new ByteChannel()
{
@Override
public int write(ByteBuffer src)
throws IOException
{
return channel.write(src);
}
@Override
public int read(ByteBuffer dst)
throws IOException
{
return channel.read(dst);
}
@Override
public boolean isOpen()
{
return channel.isOpen();
}
@Override
public void close()
throws IOException
{
channel.close();
}
};
}
}