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.resources.MessagesMessages;
040: import com.sun.xml.ws.transport.tcp.util.DumpUtils;
041: import com.sun.xml.ws.transport.tcp.util.SelectorFactory;
042: import java.io.EOFException;
043: import java.io.IOException;
044: import java.net.Socket;
045: import java.nio.ByteBuffer;
046: import java.nio.channels.SelectionKey;
047: import java.nio.channels.Selector;
048: import java.nio.channels.SocketChannel;
049: import java.util.logging.Level;
050: import java.util.logging.Logger;
051:
052: /**
053: * NIO utility to flush <code>ByteBuffer</code>
054: *
055: * @author Scott Oaks
056: * @author Alexey Stashok
057: */
058: public final class OutputWriter {
059: private static final Logger logger = Logger
060: .getLogger(com.sun.xml.ws.transport.tcp.util.TCPConstants.LoggingDomain
061: + ".dump");
062:
063: /**
064: * Flush the buffer by looping until the <code>ByteBuffer</code> is empty
065: * @param bb the ByteBuffer to write.
066: */
067: public static void flushChannel(final SocketChannel socketChannel,
068: final ByteBuffer bb) throws IOException {
069: if (logger.isLoggable(Level.FINEST)) {
070: Socket socket = socketChannel.socket();
071: logger.log(Level.FINEST, MessagesMessages
072: .WSTCP_1070_OUTPUT_WRITER_DUMP(socket
073: .getInetAddress().getHostAddress(),
074: socketChannel.socket().getPort()));
075: logger.log(Level.FINEST, DumpUtils.dumpBytes(bb));
076: }
077:
078: SelectionKey key = null;
079: Selector writeSelector = null;
080: int attempts = 0;
081: try {
082: while (bb.hasRemaining()) {
083: final int len = socketChannel.write(bb);
084: attempts++;
085: if (len < 0) {
086: throw new EOFException();
087: }
088:
089: if (len == 0) {
090: if (writeSelector == null) {
091: writeSelector = SelectorFactory.getSelector();
092: if (writeSelector == null) {
093: // Continue using the main one.
094: continue;
095: }
096: }
097:
098: key = socketChannel.register(writeSelector,
099: key.OP_WRITE);
100:
101: if (writeSelector.select(30 * 1000) == 0) {
102: if (attempts > 2) {
103: Socket socket = socketChannel.socket();
104: throw new IOException(MessagesMessages
105: .WSTCP_0019_PEER_DISCONNECTED(
106: socket.getInetAddress()
107: .getHostAddress(),
108: socketChannel.socket()
109: .getPort()));
110: }
111: } else {
112: attempts--;
113: }
114: } else {
115: attempts = 0;
116: }
117: }
118: } finally {
119: if (key != null) {
120: key.cancel();
121: key = null;
122: }
123:
124: if (writeSelector != null) {
125: // Cancel the key.
126: writeSelector.selectNow();
127: SelectorFactory.returnSelector(writeSelector);
128: }
129: }
130: }
131:
132: /**
133: * Flush the buffer by looping until the <code>ByteBuffer</code> is empty
134: * @param bb the ByteBuffer to write.
135: */
136: public static void flushChannel(final SocketChannel socketChannel,
137: final ByteBuffer[] bb) throws IOException {
138: if (logger.isLoggable(Level.FINEST)) {
139: Socket socket = socketChannel.socket();
140: logger.log(Level.FINEST, MessagesMessages
141: .WSTCP_1070_OUTPUT_WRITER_DUMP(socket
142: .getInetAddress().getHostAddress(),
143: socketChannel.socket().getPort()));
144: logger.log(Level.FINEST, DumpUtils.dumpBytes(bb));
145: }
146: SelectionKey key = null;
147: Selector writeSelector = null;
148: int attempts = 0;
149: try {
150: while (hasRemaining(bb)) {
151: final long len = socketChannel.write(bb);
152: attempts++;
153: if (len < 0) {
154: throw new EOFException();
155: }
156:
157: if (len == 0) {
158: if (writeSelector == null) {
159: writeSelector = SelectorFactory.getSelector();
160: if (writeSelector == null) {
161: // Continue using the main one.
162: continue;
163: }
164: }
165:
166: key = socketChannel.register(writeSelector,
167: key.OP_WRITE);
168:
169: if (writeSelector.select(30 * 1000) == 0) {
170: if (attempts > 2) {
171: Socket socket = socketChannel.socket();
172: throw new IOException(MessagesMessages
173: .WSTCP_0019_PEER_DISCONNECTED(
174: socket.getInetAddress()
175: .getHostAddress(),
176: socketChannel.socket()
177: .getPort()));
178: }
179: } else {
180: attempts--;
181: }
182: } else {
183: attempts = 0;
184: }
185: }
186: } finally {
187: if (key != null) {
188: key.cancel();
189: key = null;
190: }
191:
192: if (writeSelector != null) {
193: // Cancel the key.
194: writeSelector.selectNow();
195: SelectorFactory.returnSelector(writeSelector);
196: }
197: }
198: }
199:
200: private static boolean hasRemaining(final ByteBuffer[] bb) {
201: for (int i = bb.length - 1; i >= 0; i--) {
202: if (bb[i].hasRemaining()) {
203: return true;
204: }
205: }
206:
207: return false;
208: }
209: }
|