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