001: // ========================================================================
002: // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
003: // ------------------------------------------------------------------------
004: // Licensed under the Apache License, Version 2.0 (the "License");
005: // you may not use this file except in compliance with the License.
006: // You may obtain a copy of the License at
007: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: // ========================================================================
014:
015: package org.mortbay.io.nio;
016:
017: import java.io.File;
018: import java.io.FileInputStream;
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import java.nio.ByteBuffer;
023: import java.nio.channels.Channels;
024: import java.nio.channels.FileChannel;
025: import java.nio.channels.ReadableByteChannel;
026: import java.nio.channels.WritableByteChannel;
027:
028: import org.mortbay.io.AbstractBuffer;
029: import org.mortbay.io.Buffer;
030:
031: /* ------------------------------------------------------------------------------- */
032: /**
033: *
034: * @author gregw
035: */
036: public class NIOBuffer extends AbstractBuffer {
037: public final static boolean DIRECT = true, INDIRECT = false;
038:
039: protected ByteBuffer _buf;
040: private ReadableByteChannel _in;
041: private WritableByteChannel _out;
042:
043: public NIOBuffer(int size, boolean direct) {
044: super (READWRITE, NON_VOLATILE);
045: _buf = direct ? ByteBuffer.allocateDirect(size) : ByteBuffer
046: .allocate(size);
047: _buf.position(0);
048: _buf.limit(_buf.capacity());
049: }
050:
051: /**
052: * @param file
053: */
054: public NIOBuffer(File file) throws IOException {
055: super (READONLY, NON_VOLATILE);
056: FileInputStream fis = new FileInputStream(file);
057: FileChannel fc = fis.getChannel();
058: _buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
059: setGetIndex(0);
060: setPutIndex((int) file.length());
061: _access = IMMUTABLE;
062: }
063:
064: public byte[] array() {
065: if (!_buf.hasArray())
066: return null;
067: return _buf.array();
068: }
069:
070: public int capacity() {
071: return _buf.capacity();
072: }
073:
074: public byte peek(int position) {
075: return _buf.get(position);
076: }
077:
078: public int peek(int index, byte[] b, int offset, int length) {
079: int l = length;
080: if (index + l > capacity())
081: l = capacity() - index;
082: if (l <= 0)
083: return -1;
084: try {
085: _buf.position(index);
086: _buf.get(b, offset, l);
087: } finally {
088: _buf.position(0);
089: }
090:
091: return l;
092: }
093:
094: public void poke(int position, byte b) {
095: if (isReadOnly())
096: throw new IllegalStateException(__READONLY);
097: _buf.put(position, b);
098: }
099:
100: public int poke(int index, Buffer src) {
101: if (isReadOnly())
102: throw new IllegalStateException(__READONLY);
103:
104: byte[] array = src.array();
105: if (array != null) {
106: int length = poke(index, array, src.getIndex(), src
107: .length());
108: return length;
109: } else {
110: Buffer src_buf = src.buffer();
111: if (src_buf instanceof NIOBuffer) {
112: ByteBuffer src_bytebuf = ((NIOBuffer) src_buf)._buf;
113: if (src_bytebuf == _buf)
114: src_bytebuf = _buf.duplicate();
115: try {
116: int length = src.length();
117: if (length > space())
118: length = space();
119:
120: src_bytebuf.position(src.getIndex());
121: src_bytebuf.limit(src.getIndex() + length);
122:
123: _buf.position(index);
124: _buf.put(src_bytebuf);
125: return length;
126: } finally {
127: _buf.position(0);
128: src_bytebuf.limit(src_bytebuf.capacity());
129: src_bytebuf.position(0);
130: }
131: } else
132: return super .poke(index, src);
133: }
134: }
135:
136: public int poke(int index, byte[] b, int offset, int length) {
137: if (isReadOnly())
138: throw new IllegalStateException(__READONLY);
139: try {
140: if (index + length > capacity())
141: length = capacity() - index;
142: _buf.position(index);
143: _buf.put(b, offset, length);
144: return length;
145: } finally {
146: _buf.position(0);
147: }
148: }
149:
150: public ByteBuffer getByteBuffer() {
151: return _buf;
152: }
153:
154: public void setByteBuffer(ByteBuffer buf) {
155: this ._buf = buf;
156: }
157:
158: public int readFrom(InputStream in, int max) throws IOException {
159: if (_in == null || !_in.isOpen())
160: _in = Channels.newChannel(in);
161:
162: if (max > space())
163: max = space();
164: int p = putIndex();
165:
166: try {
167: _buf.position(p);
168: _buf.limit(p + max);
169: int len = _in.read(_buf);
170: if (len > 0)
171: setPutIndex(p + len);
172: else
173: _in = null;
174: return len;
175: } finally {
176: _buf.position(0);
177: _buf.limit(_buf.capacity());
178: }
179: }
180:
181: public void writeTo(OutputStream out) throws IOException {
182: if (_out == null || !_out.isOpen())
183: _out = Channels.newChannel(out);
184:
185: try {
186: _buf.position(getIndex());
187: _buf.limit(putIndex());
188: _out.write(_buf);
189: } finally {
190: _buf.position(0);
191: _buf.limit(_buf.capacity());
192: clear();
193: }
194:
195: }
196:
197: }
|