001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.transport.tcp.io;
038:
039: import com.sun.xml.ws.transport.tcp.pool.ByteBufferStreamPool;
040: import com.sun.xml.ws.transport.tcp.resources.MessagesMessages;
041: import com.sun.xml.ws.transport.tcp.util.ByteBufferFactory;
042: import com.sun.xml.ws.transport.tcp.util.FrameType;
043: import com.sun.xml.ws.transport.tcp.util.TCPConstants;
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.io.OutputStream;
047: import java.lang.ref.WeakReference;
048: import java.net.InetSocketAddress;
049: import java.net.Socket;
050: import java.nio.ByteBuffer;
051: import java.nio.channels.SocketChannel;
052: import java.util.Map;
053: import java.util.logging.Level;
054: import java.util.logging.Logger;
055:
056: /**
057: * @author Alexey Stashok
058: */
059: public final class Connection {
060: private static final Logger logger = Logger
061: .getLogger(com.sun.xml.ws.transport.tcp.util.TCPConstants.LoggingDomain);
062:
063: private static ByteBufferStreamPool<FramedMessageInputStream> byteBufferInputStreamPool = new ByteBufferStreamPool<FramedMessageInputStream>(
064: FramedMessageInputStream.class);
065: private static ByteBufferStreamPool<FramedMessageOutputStream> byteBufferOutputStreamPool = new ByteBufferStreamPool<FramedMessageOutputStream>(
066: FramedMessageOutputStream.class);
067:
068: private SocketChannel socketChannel;
069:
070: private WeakReference<BufferedMessageInputStream> inputStreamRef;
071:
072: private FramedMessageInputStream inputStream;
073: private FramedMessageOutputStream outputStream;
074:
075: /** is message framed or direct mode is used */
076: private boolean isDirectMode;
077:
078: private int messageId;
079: private int channelId;
080: private int contentId;
081:
082: public Connection(final SocketChannel socketChannel) {
083: inputStream = byteBufferInputStreamPool.take();
084: outputStream = byteBufferOutputStreamPool.take();
085: setSocketChannel(socketChannel);
086: }
087:
088: public SocketChannel getSocketChannel() {
089: return socketChannel;
090: }
091:
092: public void setSocketChannel(final SocketChannel socketChannel) {
093: this .socketChannel = socketChannel;
094: inputStream.setSocketChannel(socketChannel);
095: outputStream.setSocketChannel(socketChannel);
096: }
097:
098: /*
099: * Method should be called each time InputStream is used for new message reading!!!
100: */
101: public void prepareForReading() throws IOException {
102: if (inputStreamRef != null) {
103: final BufferedMessageInputStream is = inputStreamRef.get();
104: // if InputStream is used by some lazy reader - buffer message
105: if (inputStream.isMessageInProcess() && is != null
106: && !is.isClosed()) {
107: is.bufferMessage();
108: logger.log(Level.FINEST, MessagesMessages
109: .WSTCP_1050_CONNECTION_BUFFERING_IS(is
110: .getBufferedSize()));
111: }
112: }
113:
114: // double check input stream doesnt have earlier read message
115: if (inputStream.isMessageInProcess()) {
116: inputStream.skipToEndOfMessage();
117: }
118:
119: inputStream.reset();
120: outputStream.reset();
121:
122: inputStream.forceHeaderRead();
123:
124: channelId = inputStream.getChannelId();
125: messageId = inputStream.getMessageId();
126:
127: if (FrameType.isFrameContainsParams(messageId)) {
128: contentId = inputStream.getContentId();
129: }
130: }
131:
132: /*
133: * Method should be called <b>once</b> each time for new message reading!!!
134: * prepareForReading() should be called before!
135: */
136: public InputStream openInputStream() throws IOException {
137: final BufferedMessageInputStream is = new BufferedMessageInputStream(
138: inputStream);
139: inputStreamRef = new WeakReference<BufferedMessageInputStream>(
140: is);
141: return is;
142: }
143:
144: public OutputStream openOutputStream() {
145: outputStream.setChannelId(channelId);
146: outputStream.setMessageId(messageId);
147: outputStream.setContentId(contentId);
148:
149: return outputStream;
150: }
151:
152: public void flush() throws IOException {
153: outputStream.flushLast();
154: }
155:
156: public boolean isDirectMode() {
157: return isDirectMode;
158: }
159:
160: public void setDirectMode(final boolean isDirectMode) {
161: this .isDirectMode = isDirectMode;
162: inputStream.setDirectMode(isDirectMode);
163: outputStream.setDirectMode(isDirectMode);
164: }
165:
166: /**
167: * Get channel id
168: */
169: public int getChannelId() {
170: return channelId;
171: }
172:
173: /**
174: * Set channel id
175: */
176: public void setChannelId(final int channelId) {
177: this .channelId = channelId;
178: }
179:
180: /**
181: * Get request/response messageId of 1st frame
182: */
183: public int getMessageId() {
184: return messageId;
185: }
186:
187: /**
188: * Set request/response messageId of 1st frame
189: */
190: public void setMessageId(final int messageId) {
191: this .messageId = messageId;
192: }
193:
194: /**
195: * Get request/response contentId
196: */
197: public int getContentId() {
198: return contentId;
199: }
200:
201: /**
202: * Set request/response contentId
203: */
204: public void setContentId(final int contentId) {
205: this .contentId = contentId;
206: }
207:
208: /**
209: * Get request content properties
210: */
211: public Map<Integer, String> getContentProperties() {
212: return inputStream.getContentProperties();
213: }
214:
215: /**
216: * Set response content properties
217: */
218: public void setContentProperty(int key, String value) {
219: outputStream.setContentProperty(key, value);
220: }
221:
222: /**
223: * Set messageBuffer for InputStream
224: * some message part could be preread before
225: */
226: public void setInputStreamByteBuffer(final ByteBuffer messageBuffer) {
227: inputStream.setByteBuffer(messageBuffer);
228: }
229:
230: public void close() throws IOException {
231: if (inputStream != null) {
232: byteBufferInputStreamPool.release(inputStream);
233: inputStream = null;
234: }
235:
236: if (outputStream != null) {
237: byteBufferOutputStreamPool.release(outputStream);
238: outputStream = null;
239: }
240:
241: socketChannel.close();
242: }
243:
244: public static Connection create(final String host, final int port)
245: throws IOException {
246: if (logger.isLoggable(Level.FINE)) {
247: logger.log(Level.FINE, MessagesMessages
248: .WSTCP_1051_CONNECTION_OPEN_TCP_SOCKET(host, port));
249: }
250: final SocketChannel socketChannel = SocketChannel.open();
251: final Socket socket = socketChannel.socket();
252: socket.connect(new InetSocketAddress(host, port));
253: socketChannel.configureBlocking(false);
254:
255: final Connection connection = new Connection(socketChannel);
256:
257: final ByteBuffer byteBuffer = ByteBufferFactory.allocateView(
258: TCPConstants.DEFAULT_FRAME_SIZE,
259: TCPConstants.DEFAULT_USE_DIRECT_BUFFER);
260: byteBuffer.position(0);
261: byteBuffer.limit(0);
262:
263: connection.setInputStreamByteBuffer(byteBuffer);
264:
265: return connection;
266: }
267:
268: protected void finalize() throws Throwable {
269: close();
270: super .finalize();
271: }
272:
273: public String getHost() {
274: return getHost(socketChannel);
275: }
276:
277: public int getPort() {
278: return getPort(socketChannel);
279: }
280:
281: public String getLocalHost() {
282: return getLocalHost(socketChannel);
283: }
284:
285: public int getLocalPort() {
286: return getLocalPort(socketChannel);
287: }
288:
289: public String toString() {
290: return "host: " + getHost() + " port: " + getPort();
291: }
292:
293: public static String getHost(final SocketChannel socketChannel) {
294: return socketChannel.socket().getInetAddress().getHostAddress();
295: }
296:
297: public static int getPort(final SocketChannel socketChannel) {
298: return socketChannel.socket().getPort();
299: }
300:
301: public static String getLocalHost(final SocketChannel socketChannel) {
302: return socketChannel.socket().getLocalAddress()
303: .getHostAddress();
304: }
305:
306: public static int getLocalPort(final SocketChannel socketChannel) {
307: return socketChannel.socket().getLocalPort();
308: }
309: }
|