KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > orb > giop > Messages


1 package org.jacorb.orb.giop;
2
3 /*
4  * JacORB - a free Java ORB
5  *
6  * Copyright (C) 1997-2004 Gerald Brose.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */

22
23 import org.omg.CORBA.BAD_PARAM JavaDoc;
24 import org.omg.GIOP.MsgType_1_1;
25 import org.omg.IOP.ServiceContext JavaDoc;
26
27 /**
28  * @author Gerald Brose, FU Berlin 1999
29  * @version $Id: Messages.java,v 1.18 2004/05/06 12:40:00 nicolas Exp $
30  *
31  */

32 public class Messages
33 {
34     /**
35      * <code>MSG_HEADER_SIZE</code> is the GIOP message header size constant.
36      */

37     static final int MSG_HEADER_SIZE = 12;
38
39     /**
40      * The <code>service_context</code> array is to align the data following this
41      * array on an 8 byte boundary. This allows for adding service
42      * contexts to the header without having to remarshal everything
43      * that follows. There are already 12 bytes on the stream (the GIOP
44      * message header), so the next possible 8 byte boundary is
45      * 16. This is reached by adding an array of length 0, because that
46      * will only write a ulong for the length (0), which consumes 4
47      * bytes.
48      *
49      * This is only necessary for GIOP 1.0/1.1, because in 1.2, the
50      * service_context array is the last attribute of the
51      * [Request|Reply]Header, and the body is per spec aligned to an 8
52      * byte boundary.
53      */

54     static final ServiceContext JavaDoc[] service_context = new ServiceContext JavaDoc[0];
55
56     /**
57      * Skips over a number of service contexts in a GIOP reply message.
58      *
59      * @param buf the array of octets containing the service context
60      * @param offset the index into the buffer at which the service context
61      * starts. This should be after the length of the service context.
62      * @param length the number of service contexts
63      * @param endianness 0 for big-endian, 1 for little-endian
64      *
65      * @return the index of the octet following the service context
66      */

67     private static int skipServiceContext(byte[] buf,
68                                           int offset,
69                                           int length,
70                                           boolean little_endian )
71     {
72
73         int pos = offset;
74
75         for( int i = 0; i < length; i++)
76         {
77             // Skip the context ID long
78
pos += 4;
79
80             // Skip the octet sequence
81
pos = skipSequence( buf, pos, 1, little_endian );
82
83             //next is context id long.
84
//it has to be aligned to 4 bytes
85
int diff = pos % 4;
86             if( diff != 0 )
87             {
88                 pos += ( 4 - diff );
89             }
90         }
91
92         return pos;
93     }
94
95     /**
96      * Skips over a sequence in a GIOP message.
97      *
98      * @param buf the array of octets containing the sequence
99      * @param offset the index into the buffer at which the sequence starts.
100      * This should be where the length information begins.
101      * @param elementSize the number of octets per element in the sequence
102      * @param endianness 0 for big-endian, 1 for little-endian
103      *
104      * @return the index of the octet following the sequence
105      */

106     private static final int skipSequence( byte[] buf,
107                                            int offset,
108                                            int element_size,
109                                            boolean little_endian )
110     {
111
112         int length = readULong( buf, offset, little_endian );
113
114         return offset + 4 + length * element_size;
115     }
116
117     /** directly extract request ID from a buffer */
118
119     public static int getRequestId( byte[] buf )
120     {
121         int msg_type = getMsgType( buf );
122         int giop_minor = getGIOPMinor( buf );
123         boolean little_endian = isLittleEndian( buf );
124
125         int request_id = -1;
126
127         if( giop_minor == 2 )
128         {
129             //GIOP 1.2
130

131             if( msg_type == MsgType_1_1._Request ||
132                 msg_type == MsgType_1_1._LocateRequest ||
133                 msg_type == MsgType_1_1._Reply ||
134                 msg_type == MsgType_1_1._LocateReply ||
135                 msg_type == MsgType_1_1._CancelRequest ||
136                 msg_type == MsgType_1_1._Fragment )
137             {
138                 //easy for GIOP 1.2, it's right after the message
139
//header
140
request_id = readULong( buf, MSG_HEADER_SIZE, little_endian );
141             }
142             else
143             {
144                 throw new BAD_PARAM JavaDoc
145                     ("Messages of type " + msg_type + " don't have request ids");
146             }
147         }
148         else if( giop_minor == 0 || giop_minor == 1 )
149         {
150             if( msg_type == MsgType_1_1._Request ||
151                 msg_type == MsgType_1_1._Reply )
152             {
153                 // service contexts are the first entry in the header
154

155                 //get the number of individual service contexts
156
int service_ctx_length = readULong( buf,
157                                                     MSG_HEADER_SIZE,
158                                                     little_endian );
159
160                 if( service_ctx_length == 0 )
161                 {
162                     //array of length 0, so request id folows the
163
//array length entry
164

165                     request_id = readULong( buf,
166                                             MSG_HEADER_SIZE + 4,
167                                             little_endian );
168                 }
169                 else
170                 {
171                     //get the first index after the contexts array
172
int pos = skipServiceContext( buf,
173                                                   MSG_HEADER_SIZE + 4, // 4 bytes is ulong
174
service_ctx_length,
175                                                   little_endian );
176
177                     //the request id follows the body
178
request_id = readULong( buf, pos, little_endian );
179                 }
180             }
181             else if( msg_type == MsgType_1_1._LocateRequest ||
182                      msg_type == MsgType_1_1._LocateReply )
183             {
184                 //easy, it's right after the message header
185
request_id = readULong( buf, MSG_HEADER_SIZE, little_endian );
186             }
187             else
188             {
189                 throw new BAD_PARAM JavaDoc
190                     ("Messages of type " + msg_type + " don't have request ids");
191             }
192         }
193
194         return request_id;
195     }
196
197     public static final int getMsgSize( byte[] buf )
198     {
199         return readULong( buf, 8, isLittleEndian( buf ) );
200     }
201
202     public static final int readULong( byte[] buf,
203                                        int pos,
204                                        boolean little_endian )
205     {
206     if( little_endian )
207         {
208         return (( (buf[pos+3] & 0xff) << 24) +
209             ( (buf[pos+2] & 0xff) << 16) +
210             ( (buf[pos+1] & 0xff) << 8) +
211             ( (buf[pos] & 0xff) << 0));
212         }
213     else //big endian
214
{
215         return (( (buf[pos] & 0xff) << 24) +
216             ( (buf[pos+1] & 0xff) << 16) +
217             ( (buf[pos+2] & 0xff) << 8) +
218             ( (buf[pos+3] & 0xff) << 0));
219         }
220     }
221
222     public static final boolean isLittleEndian( byte[] buf )
223     {
224         //this is new for GIOP 1.1/1.2
225
return (0x01 & buf[6]) != 0;
226     }
227
228     public static final boolean moreFragmentsFollow( byte[] buf )
229     {
230         //this is new for GIOP 1.1/1.2
231
return (0x02 & buf[6]) != 0;
232     }
233
234     public static final int getMsgType( byte[] buf )
235     {
236         return buf[7];
237     }
238
239     public static final int getGIOPMajor( byte[] buf )
240     {
241         return buf[4];
242     }
243
244     public static final int getGIOPMinor( byte[] buf )
245     {
246         return buf[5];
247     }
248
249     public static final boolean responseExpected( byte flags )
250     {
251         return flags == (byte)0x01 || flags == (byte)0x03;
252     }
253
254     public static final byte responseFlags( boolean response_expected )
255     {
256         return (byte) (response_expected ? 0x03 : 0x00);
257     }
258
259 }
260
Popular Tags