1 /* ChannelWriter.java -- nio / writer bridge
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java
.io
.IOException
;
42 import java
.io
.Writer
;
43 import java
.nio
.ByteBuffer
;
44 import java
.nio
.CharBuffer
;
45 import java
.nio
.channels
.WritableByteChannel
;
46 import java
.nio
.charset
.CharsetEncoder
;
47 import java
.nio
.charset
.CoderResult
;
50 * A Writer implementation that works by wrapping an NIO channel.
52 public class ChannelWriter
55 private static final int DEFAULT_BUFFER_CAP
= 8192;
60 private WritableByteChannel byteChannel
;
65 private CharsetEncoder enc
;
68 * The byte buffer. Translated characters are stored here on their way out.
70 private ByteBuffer byteBuffer
;
73 * The character buffer. Characters are stored here on their way into
76 private CharBuffer charBuffer
;
78 private void writeBuffer() throws IOException
81 byteChannel
.write(byteBuffer
);
85 * Create a new instance, given the output byte channel, the encoder
86 * to use, and the minimum buffer capacity.
88 public ChannelWriter(WritableByteChannel ch
, CharsetEncoder enc
,
91 this.byteChannel
= ch
;
93 if (minBufferCap
== -1)
94 minBufferCap
= DEFAULT_BUFFER_CAP
;
96 = ByteBuffer
.allocate((int) (minBufferCap
* enc
.maxBytesPerChar()));
97 this.charBuffer
= CharBuffer
.allocate(minBufferCap
);
98 this.charBuffer
.clear();
102 * @see java.io.Writer#flush()
104 public void flush() throws IOException
106 // Presumably if we have characters in our buffer, it is
107 // due to an underflow. So we don't bother trying to flush
112 * @see java.io.Writer#close()
114 public void close() throws IOException
119 throw new IOException("writer already closed");
123 CoderResult res
= enc
.encode(charBuffer
, byteBuffer
, true);
124 if (res
.isError() || res
.isMalformed() || res
.isUnmappable())
125 res
.throwException();
129 res
= enc
.flush(byteBuffer
);
130 if (res
.isError() || res
.isMalformed() || res
.isUnmappable())
131 res
.throwException();
138 * @see java.io.Writer#write(char[], int, int)
140 public void write(char[] buf
, int offset
, int len
) throws IOException
145 throw new IOException("writer already closed");
149 // Copy data into our character buffer.
150 int allowed
= Math
.min(charBuffer
.remaining(), len
);
151 charBuffer
.put(buf
, offset
, allowed
);
152 // Update for the next pass through the loop.
156 // If we didn't make any progress, we want to clean up
157 // and save our state for the next write().
160 if (len
<= charBuffer
.remaining())
162 charBuffer
.put(buf
, offset
, len
);
167 CharBuffer ncb
= CharBuffer
.allocate(charBuffer
.length()
170 ncb
.put(buf
, offset
, len
);
179 CoderResult res
= enc
.encode(charBuffer
, byteBuffer
, false);
180 // Compact here, as we want to leave the buffer in the
181 // right state for any future put()s.
182 charBuffer
.compact();
183 if (res
.isError() || res
.isMalformed() || res
.isUnmappable())
184 res
.throwException();
185 // Write the byte buffer to the output channel.