KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jk > common > MsgAjp


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.jk.common;
18
19 import java.io.IOException JavaDoc;
20
21 import org.apache.jk.core.Msg;
22 import org.apache.tomcat.util.buf.ByteChunk;
23 import org.apache.tomcat.util.buf.MessageBytes;
24
25 /**
26  * A single packet for communication between the web server and the
27  * container. Designed to be reused many times with no creation of
28  * garbage. Understands the format of data types for these packets.
29  * Can be used (somewhat confusingly) for both incoming and outgoing
30  * packets.
31  *
32  * See Ajp14/Ajp13Packet.java.
33  *
34  * @author Henri Gomez [hgomez@apache.org]
35  * @author Dan Milstein [danmil@shore.net]
36  * @author Keith Wannamaker [Keith@Wannamaker.org]
37  * @author Kevin Seguin
38  * @author Costin Manolache
39  */

40 public class MsgAjp extends Msg {
41     private static org.apache.commons.logging.Log log=
42         org.apache.commons.logging.LogFactory.getLog( MsgAjp.class );
43
44     // that's the original buffer size in ajp13 - otherwise we'll get interoperability problems.
45
private byte buf[]=new byte[8*1024];
46     // The current read or write position in the buffer
47
private int pos;
48     /**
49      * This actually means different things depending on whether the
50      * packet is read or write. For read, it's the length of the
51      * payload (excluding the header). For write, it's the length of
52      * the packet as a whole (counting the header). Oh, well.
53      */

54     private int len;
55
56
57     
58     
59     /**
60      * Prepare this packet for accumulating a message from the container to
61      * the web server. Set the write position to just after the header
62      * (but leave the length unwritten, because it is as yet unknown).
63      */

64     public void reset() {
65         len = 4;
66         pos = 4;
67     }
68     
69     /**
70      * For a packet to be sent to the web server, finish the process of
71      * accumulating data and write the length of the data payload into
72      * the header.
73      */

74     public void end() {
75         len=pos;
76         int dLen=len-4;
77
78         buf[0] = (byte)0x41;
79         buf[1] = (byte)0x42;
80         buf[2]= (byte)((dLen>>>8 ) & 0xFF );
81         buf[3] = (byte)(dLen & 0xFF);
82     }
83
84     public byte[] getBuffer() {
85         return buf;
86     }
87
88     public int getLen() {
89         return len;
90     }
91     
92     // ============ Data Writing Methods ===================
93

94     /**
95      * Add an int.
96      *
97      * @param val The integer to write.
98      */

99     public void appendInt( int val ) {
100         buf[pos++] = (byte) ((val >>> 8) & 0xFF);
101         buf[pos++] = (byte) (val & 0xFF);
102     }
103
104     public void appendByte( int val ) {
105         buf[pos++] = (byte)val;
106     }
107     
108     public void appendLongInt( int val ) {
109         buf[pos++] = (byte) ((val >>> 24) & 0xFF);
110         buf[pos++] = (byte) ((val >>> 16) & 0xFF);
111         buf[pos++] = (byte) ((val >>> 8) & 0xFF);
112         buf[pos++] = (byte) (val & 0xFF);
113     }
114
115     /**
116      * Write a String out at the current write position. Strings are
117      * encoded with the length in two bytes first, then the string, and
118      * then a terminating \0 (which is <B>not</B> included in the
119      * encoded length). The terminator is for the convenience of the C
120      * code, where it saves a round of copying. A null string is
121      * encoded as a string with length 0.
122      */

123     public void appendBytes(MessageBytes mb) throws IOException JavaDoc {
124         if(mb==null || mb.isNull() ) {
125             appendInt( 0);
126             appendByte(0);
127             return;
128         }
129
130         // XXX Convert !!
131
ByteChunk bc= mb.getByteChunk();
132         appendByteChunk(bc);
133     }
134
135     public void appendByteChunk(ByteChunk bc) throws IOException JavaDoc {
136         if(bc==null) {
137             log.error("appendByteChunk() null");
138             appendInt( 0);
139             appendByte(0);
140             return;
141         }
142
143         byte[] bytes = bc.getBytes();
144         int start=bc.getStart();
145         appendInt( bc.getLength() );
146         cpBytes(bytes, start, bc.getLength());
147         appendByte(0);
148     }
149
150     /**
151      * Copy a chunk of bytes into the packet, starting at the current
152      * write position. The chunk of bytes is encoded with the length
153      * in two bytes first, then the data itself, and finally a
154      * terminating \0 (which is <B>not</B> included in the encoded
155      * length).
156      *
157      * @param b The array from which to copy bytes.
158      * @param off The offset into the array at which to start copying
159      * @param numBytes The number of bytes to copy.
160      */

161     public void appendBytes( byte b[], int off, int numBytes ) {
162         appendInt( numBytes );
163         cpBytes( b, off, numBytes );
164         appendByte(0);
165     }
166     
167     private void cpBytes( byte b[], int off, int numBytes ) {
168         if( pos + numBytes >= buf.length ) {
169             log.error("Buffer overflow: buffer.len=" + buf.length + " pos=" +
170                       pos + " data=" + numBytes );
171             dump("Overflow/coBytes");
172             log.error( "Overflow ", new Throwable JavaDoc());
173             return;
174         }
175         System.arraycopy( b, off, buf, pos, numBytes);
176         pos += numBytes;
177         // buf[pos + numBytes] = 0; // Terminating \0
178
}
179     
180
181     
182     // ============ Data Reading Methods ===================
183

184     /**
185      * Read an integer from packet, and advance the read position past
186      * it. Integers are encoded as two unsigned bytes with the
187      * high-order byte first, and, as far as I can tell, in
188      * little-endian order within each byte.
189      */

190     public int getInt() {
191         int b1 = buf[pos++] & 0xFF; // No swap, Java order
192
int b2 = buf[pos++] & 0xFF;
193
194         return (b1<<8) + b2;
195     }
196
197     public int peekInt() {
198         int b1 = buf[pos] & 0xFF; // No swap, Java order
199
int b2 = buf[pos+1] & 0xFF;
200
201         return (b1<<8) + b2;
202     }
203
204     public byte getByte() {
205         byte res = buf[pos++];
206         return res;
207     }
208
209     public byte peekByte() {
210         byte res = buf[pos];
211         return res;
212     }
213
214     public void getBytes(MessageBytes mb) {
215         int length = getInt();
216         if( (length == 0xFFFF) || (length == -1) ) {
217             mb.recycle();
218             return;
219         }
220         mb.setBytes( buf, pos, length );
221         pos += length;
222         pos++; // Skip the terminating \0
223
}
224     
225     /**
226      * Copy a chunk of bytes from the packet into an array and advance
227      * the read position past the chunk. See appendBytes() for details
228      * on the encoding.
229      *
230      * @return The number of bytes copied.
231      */

232     public int getBytes(byte dest[]) {
233         int length = getInt();
234         if( length > buf.length ) {
235             // XXX Should be if(pos + length > buff.legth)?
236
log.error("getBytes() buffer overflow " + length + " " + buf.length );
237         }
238     
239         if( (length == 0xFFFF) || (length == -1) ) {
240             log.info("Null string " + length);
241             return 0;
242         }
243
244         System.arraycopy( buf, pos, dest, 0, length );
245         pos += length;
246         pos++; // Skip terminating \0 XXX I believe this is wrong but harmless
247
return length;
248     }
249
250     /**
251      * Read a 32 bits integer from packet, and advance the read position past
252      * it. Integers are encoded as four unsigned bytes with the
253      * high-order byte first, and, as far as I can tell, in
254      * little-endian order within each byte.
255      */

256     public int getLongInt() {
257         int b1 = buf[pos++] & 0xFF; // No swap, Java order
258
b1 <<= 8;
259         b1 |= (buf[pos++] & 0xFF);
260         b1 <<= 8;
261         b1 |= (buf[pos++] & 0xFF);
262         b1 <<=8;
263         b1 |= (buf[pos++] & 0xFF);
264         return b1;
265     }
266
267     public int getHeaderLength() {
268         return 4;
269     }
270
271     public int processHeader() {
272         pos = 0;
273         int mark = getInt();
274         len = getInt();
275         
276         if( mark != 0x1234 && mark != 0x4142 ) {
277             // XXX Logging
278
log.error("BAD packet signature " + mark);
279             dump( "In: " );
280             return -1;
281         }
282
283         if( log.isDebugEnabled() )
284             log.debug( "Received " + len + " " + buf[0] );
285         return len;
286     }
287     
288     public void dump(String JavaDoc msg) {
289         if( log.isDebugEnabled() )
290             log.debug( msg + ": " + buf + " " + pos +"/" + (len + 4));
291         int max=pos;
292         if( len + 4 > pos )
293             max=len+4;
294         if( max >1000 ) max=1000;
295         if( log.isDebugEnabled() )
296             for( int j=0; j < max; j+=16 )
297                 log.debug( hexLine( buf, j, len ));
298     
299     }
300
301     /* -------------------- Utilities -------------------- */
302     // XXX Move to util package
303

304     public static String JavaDoc hexLine( byte buf[], int start, int len ) {
305         StringBuffer JavaDoc sb=new StringBuffer JavaDoc();
306         for( int i=start; i< start+16 ; i++ ) {
307             if( i < len + 4)
308                 sb.append( hex( buf[i] ) + " ");
309             else
310                 sb.append( " " );
311         }
312         sb.append(" | ");
313         for( int i=start; i < start+16 && i < len + 4; i++ ) {
314             if( ! Character.isISOControl( (char)buf[i] ))
315                 sb.append( new Character JavaDoc((char)buf[i]) );
316             else
317                 sb.append( "." );
318         }
319         return sb.toString();
320     }
321
322     private static String JavaDoc hex( int x ) {
323         // if( x < 0) x=256 + x;
324
String JavaDoc h=Integer.toHexString( x );
325         if( h.length() == 1 ) h = "0" + h;
326         return h.substring( h.length() - 2 );
327     }
328
329 }
330
Popular Tags