001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.vfs;
030:
031: import javax.net.ssl.SSLContext;
032: import javax.net.ssl.SSLSocketFactory;
033: import java.io.IOException;
034: import java.io.InputStream;
035: import java.io.OutputStream;
036: import java.net.Socket;
037: import java.net.SocketException;
038:
039: /**
040: * Implementation of a TCP stream. Mostly this just forwards the
041: * request to the underlying socket streams.
042: */
043: class TcpStream extends StreamImpl {
044: private Socket _s;
045: private InputStream _is;
046: private OutputStream _os;
047:
048: private TcpStream(TcpPath path, long timeout) throws IOException {
049: setPath(path);
050:
051: //_s = new Socket(path.getHost(), path.getPort());
052: _s = new Socket();
053:
054: if (timeout > 0)
055: _s.connect(path.getSocketAddress(), (int) timeout);
056: else
057: _s.connect(path.getSocketAddress());
058:
059: if (!_s.isConnected())
060: throw new IOException("connection timeout");
061:
062: if (timeout < 0)
063: timeout = 120000;
064:
065: _s.setSoTimeout((int) timeout);
066:
067: try {
068: if (path instanceof TcpsPath) {
069: SSLContext context = SSLContext.getInstance("TLS");
070:
071: javax.net.ssl.TrustManager tm = new javax.net.ssl.X509TrustManager() {
072: public java.security.cert.X509Certificate[] getAcceptedIssuers() {
073: return null;
074: }
075:
076: public void checkClientTrusted(
077: java.security.cert.X509Certificate[] cert,
078: String foo) {
079: }
080:
081: public void checkServerTrusted(
082: java.security.cert.X509Certificate[] cert,
083: String foo) {
084: }
085: };
086:
087: context.init(null,
088: new javax.net.ssl.TrustManager[] { tm }, null);
089: SSLSocketFactory factory = context.getSocketFactory();
090:
091: _s = factory.createSocket(_s, path.getHost(), path
092: .getPort(), true);
093: }
094: } catch (IOException e) {
095: throw e;
096: } catch (RuntimeException e) {
097: throw e;
098: } catch (Exception e) {
099: throw new IOExceptionWrapper(e);
100: }
101:
102: _is = _s.getInputStream();
103: _os = _s.getOutputStream();
104: }
105:
106: public void setAttribute(String name, Object value) {
107: if (name.equals("timeout")) {
108: try {
109: if (value instanceof Number)
110: _s.setSoTimeout(((Number) value).intValue());
111: else
112: _s.setSoTimeout(Integer.parseInt(String
113: .valueOf(value)));
114: } catch (SocketException e) {
115: }
116: }
117: }
118:
119: static TcpStream openRead(TcpPath path, long timeout)
120: throws IOException {
121: return new TcpStream(path, timeout);
122: }
123:
124: static TcpStream openReadWrite(TcpPath path, long timeout)
125: throws IOException {
126: return new TcpStream(path, timeout);
127: }
128:
129: public boolean canWrite() {
130: return _os != null;
131: }
132:
133: /**
134: * Writes a buffer to the underlying stream.
135: *
136: * @param buffer the byte array to write.
137: * @param offset the offset into the byte array.
138: * @param length the number of bytes to write.
139: * @param isEnd true when the write is flushing a close.
140: */
141: public void write(byte[] buf, int offset, int length, boolean isEnd)
142: throws IOException {
143: if (_os != null)
144: _os.write(buf, offset, length);
145: }
146:
147: public boolean canRead() {
148: return _is != null;
149: }
150:
151: public int getAvailable() throws IOException {
152: if (_is != null)
153: return _is.available();
154: else
155: return -1;
156: }
157:
158: public int read(byte[] buf, int offset, int length)
159: throws IOException {
160: if (_is != null)
161: return _is.read(buf, offset, length);
162: else
163: return -1;
164: }
165:
166: public void closeWrite() throws IOException {
167: OutputStream os = _os;
168: _os = null;
169:
170: try {
171: if (os != null)
172: _s.shutdownOutput();
173: } finally {
174: if (_is == null) {
175: Socket s = _s;
176: _s = null;
177:
178: if (s != null)
179: s.close();
180: }
181: }
182: }
183:
184: public void close() throws IOException {
185: InputStream is = _is;
186: _is = null;
187:
188: OutputStream os = _os;
189: _os = null;
190:
191: Socket s = _s;
192: _s = null;
193:
194: try {
195: if (os != null)
196: os.close();
197:
198: if (is != null)
199: is.close();
200: } finally {
201: if (s != null)
202: s.close();
203: }
204: }
205: }
|