1 /***
2 *
3 * Copyright 2004 Hiram Chirino
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 * use this file except in compliance with the License. You may obtain a copy of
7 * the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17 package org.activeio.packet;
18
19 import java.io.DataOutput;
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.lang.reflect.Constructor;
23
24 import org.activeio.Packet;
25
26 /***
27 * Appends two packets together.
28 *
29 * @version $Revision$
30 */
31 final public class AppendedPacket implements Packet {
32
33 private final Packet first;
34 private final Packet last;
35
36 private final int capacity;
37 private final int firstCapacity;
38
39 static public Packet join(Packet first, Packet last) {
40 if( first.hasRemaining() ) {
41 if( last.hasRemaining() ) {
42
43
44
45
46 return new AppendedPacket(first.slice(), last.slice());
47 } else {
48 return first.slice();
49 }
50 } else {
51 if( last.hasRemaining() ) {
52 return last.slice();
53 } else {
54 return EmptyPacket.EMPTY_PACKET;
55 }
56 }
57 }
58
59 /***
60 * @deprecated use {@see #join(Packet, Packet)} instead.
61 */
62 public AppendedPacket(Packet first, Packet second) {
63 this.first = first;
64 this.last = second;
65 this.firstCapacity = first.capacity();
66 this.capacity = first.capacity()+last.capacity();
67 clear();
68 }
69
70 public void position(int position) {
71 if( position <= firstCapacity ) {
72 last.position(0);
73 first.position(position);
74 } else {
75 last.position(position-firstCapacity);
76 first.position(firstCapacity);
77 }
78 }
79
80 public void limit(int limit) {
81 if( limit <= firstCapacity ) {
82 last.limit(0);
83 first.limit(limit);
84 } else {
85 last.limit(limit-firstCapacity);
86 first.limit(firstCapacity);
87 }
88 }
89
90 public Packet slice() {
91 return join(first,last);
92 }
93
94 public Packet duplicate() {
95 return new AppendedPacket(first.duplicate(), last.duplicate());
96 }
97
98 public Object duplicate(ClassLoader cl) throws IOException {
99 try {
100 Class pclazz = cl.loadClass(Packet.class.getName());
101 Class clazz = cl.loadClass(AppendedPacket.class.getName());
102 Constructor constructor = clazz.getConstructor(new Class[]{pclazz, pclazz});
103 return constructor.newInstance(new Object[]{first.duplicate(cl), last.duplicate(cl)});
104 } catch (Throwable e) {
105 throw (IOException)new IOException("Could not duplicate packet in a different classloader: "+e).initCause(e);
106 }
107 }
108
109 public void flip() {
110 limit(position());
111 position(0);
112 }
113
114 public int position() {
115 return first.position()+last.position();
116 }
117
118 public int limit() {
119 return first.limit()+last.limit();
120 }
121
122 public int remaining() {
123 return first.remaining()+last.remaining();
124 }
125
126 public void rewind() {
127 first.rewind();
128 last.rewind();
129 }
130
131 public boolean hasRemaining() {
132 return first.hasRemaining()||last.hasRemaining();
133 }
134
135 public void clear() {
136 first.clear();
137 last.clear();
138 }
139
140 public int capacity() {
141 return capacity;
142 }
143
144 public void writeTo(OutputStream out) throws IOException {
145 first.writeTo(out);
146 last.writeTo(out);
147 }
148
149 public void writeTo(DataOutput out) throws IOException {
150 first.writeTo(out);
151 last.writeTo(out);
152 }
153
154
155 /***
156 * @see org.activeio.Packet#read()
157 */
158 public int read() {
159 if( first.hasRemaining() ) {
160 return first.read();
161 } else if( last.hasRemaining() ) {
162 return last.read();
163 } else {
164 return -1;
165 }
166 }
167
168 /***
169 * @see org.activeio.Packet#read(byte[], int, int)
170 */
171 public int read(byte[] data, int offset, int length) {
172
173 int rc1 = first.read(data, offset, length);
174 if( rc1==-1 ) {
175 int rc2 = last.read(data, offset, length);
176 return ( rc2==-1 ) ? -1 : rc2;
177 } else {
178 int rc2 = last.read(data, offset+rc1, length-rc1);
179 return ( rc2==-1 ) ? rc1 : rc1+rc2;
180 }
181
182 }
183
184 /***
185 * @see org.activeio.Packet#write(int)
186 */
187 public boolean write(int data) {
188 if( first.hasRemaining() ) {
189 return first.write(data);
190 } else if( last.hasRemaining() ) {
191 return last.write(data);
192 } else {
193 return false;
194 }
195 }
196
197 /***
198 * @see org.activeio.Packet#write(byte[], int, int)
199 */
200 public int write(byte[] data, int offset, int length) {
201 int rc1 = first.write(data, offset, length);
202 if( rc1==-1 ) {
203 int rc2 = last.write(data, offset, length);
204 return ( rc2==-1 ) ? -1 : rc2;
205 } else {
206 int rc2 = last.write(data, offset+rc1, length-rc1);
207 return ( rc2==-1 ) ? rc1 : rc1+rc2;
208 }
209 }
210
211 public int read(Packet dest) {
212 int rc = first.read(dest);
213 rc += last.read(dest);
214 return rc;
215 }
216
217 public String toString() {
218 return "{position="+position()+",limit="+limit()+",capacity="+capacity()+"}";
219 }
220
221 public Object narrow(Class target) {
222 if( target.isAssignableFrom(getClass()) ) {
223 return this;
224 }
225 Object object = first.narrow(target);
226 if( object == null )
227 object = last.narrow(target);
228 return object;
229 }
230
231 public ByteSequence asByteSequence() {
232
233 return null;
234 }
235
236 public byte[] sliceAsBytes() {
237
238 return null;
239 }
240
241 public void dispose() {
242 first.dispose();
243 last.dispose();
244 }
245
246 }