Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / java / nio / ChannelWriter.java
blob8e533ccbfe4cdcd28dc1a89890c124b607d5c04d
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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. */
39 package gnu.java.nio;
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;
49 /**
50 * A Writer implementation that works by wrapping an NIO channel.
52 public class ChannelWriter
53 extends Writer
55 private static final int DEFAULT_BUFFER_CAP = 8192;
57 /**
58 * The output channel.
60 private WritableByteChannel byteChannel;
62 /**
63 * The encoder to use.
65 private CharsetEncoder enc;
67 /**
68 * The byte buffer. Translated characters are stored here on their way out.
70 private ByteBuffer byteBuffer;
72 /**
73 * The character buffer. Characters are stored here on their way into
74 * the encoder.
76 private CharBuffer charBuffer;
78 private void writeBuffer() throws IOException
80 byteBuffer.flip();
81 byteChannel.write(byteBuffer);
84 /**
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,
89 int minBufferCap)
91 this.byteChannel = ch;
92 this.enc = enc;
93 if (minBufferCap == -1)
94 minBufferCap = DEFAULT_BUFFER_CAP;
95 this.byteBuffer
96 = ByteBuffer.allocate((int) (minBufferCap * enc.maxBytesPerChar()));
97 this.charBuffer = CharBuffer.allocate(minBufferCap);
98 this.charBuffer.clear();
101 /* (non-Javadoc)
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
108 // that here.
111 /* (non-Javadoc)
112 * @see java.io.Writer#close()
114 public void close() throws IOException
116 synchronized (lock)
118 if (enc == null)
119 throw new IOException("writer already closed");
121 byteBuffer.clear();
122 charBuffer.flip();
123 CoderResult res = enc.encode(charBuffer, byteBuffer, true);
124 if (res.isError() || res.isMalformed() || res.isUnmappable())
125 res.throwException();
126 writeBuffer();
128 byteBuffer.clear();
129 res = enc.flush(byteBuffer);
130 if (res.isError() || res.isMalformed() || res.isUnmappable())
131 res.throwException();
132 writeBuffer();
133 enc = null;
137 /* (non-Javadoc)
138 * @see java.io.Writer#write(char[], int, int)
140 public void write(char[] buf, int offset, int len) throws IOException
142 synchronized (lock)
144 if (enc == null)
145 throw new IOException("writer already closed");
146 int lastLen = -1;
147 while (len > 0)
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.
153 offset += allowed;
154 len -= allowed;
155 charBuffer.flip();
156 // If we didn't make any progress, we want to clean up
157 // and save our state for the next write().
158 if (len == lastLen)
160 if (len <= charBuffer.remaining())
162 charBuffer.put(buf, offset, len);
163 charBuffer.flip();
165 else
167 CharBuffer ncb = CharBuffer.allocate(charBuffer.length()
168 + len);
169 ncb.put(charBuffer);
170 ncb.put(buf, offset, len);
171 charBuffer = ncb;
173 break;
175 lastLen = len;
177 // Convert.
178 byteBuffer.clear();
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.
186 writeBuffer();