1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.buffer;
17
18 import java.lang.ref.ReferenceQueue;
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class DirectChannelBufferFactory extends AbstractChannelBufferFactory {
38
39 private static final DirectChannelBufferFactory INSTANCE_BE =
40 new DirectChannelBufferFactory(ByteOrder.BIG_ENDIAN);
41
42 private static final DirectChannelBufferFactory INSTANCE_LE =
43 new DirectChannelBufferFactory(ByteOrder.LITTLE_ENDIAN);
44
45 public static ChannelBufferFactory getInstance() {
46 return INSTANCE_BE;
47 }
48
49 public static ChannelBufferFactory getInstance(ByteOrder defaultEndianness) {
50 if (defaultEndianness == ByteOrder.BIG_ENDIAN) {
51 return INSTANCE_BE;
52 } else if (defaultEndianness == ByteOrder.LITTLE_ENDIAN) {
53 return INSTANCE_LE;
54 } else if (defaultEndianness == null) {
55 throw new NullPointerException("defaultEndianness");
56 } else {
57 throw new IllegalStateException("Should not reach here");
58 }
59 }
60
61 private final Object bigEndianLock = new Object();
62 private final Object littleEndianLock = new Object();
63 private final int preallocatedBufferCapacity;
64 private ChannelBuffer preallocatedBigEndianBuffer = null;
65 private int preallocatedBigEndianBufferPosition;
66 private ChannelBuffer preallocatedLittleEndianBuffer = null;
67 private int preallocatedLittleEndianBufferPosition;
68
69
70
71
72
73 public DirectChannelBufferFactory() {
74 this(ByteOrder.BIG_ENDIAN);
75 }
76
77
78
79
80
81 public DirectChannelBufferFactory(int preallocatedBufferCapacity) {
82 this(ByteOrder.BIG_ENDIAN, preallocatedBufferCapacity);
83 }
84
85
86
87
88
89
90 public DirectChannelBufferFactory(ByteOrder defaultOrder) {
91 this(defaultOrder, 1048576);
92 }
93
94
95
96
97
98
99 public DirectChannelBufferFactory(ByteOrder defaultOrder, int preallocatedBufferCapacity) {
100 super(defaultOrder);
101 if (preallocatedBufferCapacity <= 0) {
102 throw new IllegalArgumentException(
103 "preallocatedBufferCapacity must be greater than 0: " + preallocatedBufferCapacity);
104 }
105
106 this.preallocatedBufferCapacity = preallocatedBufferCapacity;
107 }
108
109 public ChannelBuffer getBuffer(ByteOrder order, int capacity) {
110 if (order == null) {
111 throw new NullPointerException("order");
112 }
113 if (capacity < 0) {
114 throw new IllegalArgumentException("capacity: " + capacity);
115 }
116 if (capacity == 0) {
117 return ChannelBuffers.EMPTY_BUFFER;
118 }
119 if (capacity >= preallocatedBufferCapacity) {
120 return ChannelBuffers.directBuffer(order, capacity);
121 }
122
123 ChannelBuffer slice;
124 if (order == ByteOrder.BIG_ENDIAN) {
125 slice = allocateBigEndianBuffer(capacity);
126 } else {
127 slice = allocateLittleEndianBuffer(capacity);
128 }
129 slice.clear();
130 return slice;
131 }
132
133 public ChannelBuffer getBuffer(ByteOrder order, byte[] array, int offset, int length) {
134 if (array == null) {
135 throw new NullPointerException("array");
136 }
137 if (offset < 0) {
138 throw new IndexOutOfBoundsException("offset: " + offset);
139 }
140 if (length == 0) {
141 return ChannelBuffers.EMPTY_BUFFER;
142 }
143 if (offset + length > array.length) {
144 throw new IndexOutOfBoundsException("length: " + length);
145 }
146
147 ChannelBuffer buf = getBuffer(order, length);
148 buf.writeBytes(array, offset, length);
149 return buf;
150 }
151
152 public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
153 if (!nioBuffer.isReadOnly() && nioBuffer.isDirect()) {
154 return ChannelBuffers.wrappedBuffer(nioBuffer);
155 }
156
157 ChannelBuffer buf = getBuffer(nioBuffer.order(), nioBuffer.remaining());
158 int pos = nioBuffer.position();
159 buf.writeBytes(nioBuffer);
160 nioBuffer.position(pos);
161 return buf;
162 }
163
164 private ChannelBuffer allocateBigEndianBuffer(int capacity) {
165 ChannelBuffer slice;
166 synchronized (bigEndianLock) {
167 if (preallocatedBigEndianBuffer == null) {
168 preallocatedBigEndianBuffer = ChannelBuffers.directBuffer(ByteOrder.BIG_ENDIAN, preallocatedBufferCapacity);
169 slice = preallocatedBigEndianBuffer.slice(0, capacity);
170 preallocatedBigEndianBufferPosition = capacity;
171 } else if (preallocatedBigEndianBuffer.capacity() - preallocatedBigEndianBufferPosition >= capacity) {
172 slice = preallocatedBigEndianBuffer.slice(preallocatedBigEndianBufferPosition, capacity);
173 preallocatedBigEndianBufferPosition += capacity;
174 } else {
175 preallocatedBigEndianBuffer = ChannelBuffers.directBuffer(ByteOrder.BIG_ENDIAN, preallocatedBufferCapacity);
176 slice = preallocatedBigEndianBuffer.slice(0, capacity);
177 preallocatedBigEndianBufferPosition = capacity;
178 }
179 }
180 return slice;
181 }
182
183 private ChannelBuffer allocateLittleEndianBuffer(int capacity) {
184 ChannelBuffer slice;
185 synchronized (littleEndianLock) {
186 if (preallocatedLittleEndianBuffer == null) {
187 preallocatedLittleEndianBuffer = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, preallocatedBufferCapacity);
188 slice = preallocatedLittleEndianBuffer.slice(0, capacity);
189 preallocatedLittleEndianBufferPosition = capacity;
190 } else if (preallocatedLittleEndianBuffer.capacity() - preallocatedLittleEndianBufferPosition >= capacity) {
191 slice = preallocatedLittleEndianBuffer.slice(preallocatedLittleEndianBufferPosition, capacity);
192 preallocatedLittleEndianBufferPosition += capacity;
193 } else {
194 preallocatedLittleEndianBuffer = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, preallocatedBufferCapacity);
195 slice = preallocatedLittleEndianBuffer.slice(0, capacity);
196 preallocatedLittleEndianBufferPosition = capacity;
197 }
198 }
199 return slice;
200 }
201 }