MessageBase.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.corba.se.impl.protocol.giopmsgheaders;
27
28import java.io.IOException;
29import java.lang.Class;
30import java.lang.reflect.Constructor;
31import java.nio.ByteBuffer;
32import java.util.Iterator;
33
34import org.omg.CORBA.CompletionStatus;
35import org.omg.CORBA.INTERNAL;
36import org.omg.CORBA.MARSHAL;
37import org.omg.CORBA.Principal;
38import org.omg.CORBA.SystemException;
39import org.omg.IOP.TaggedProfile;
40
41import com.sun.corba.se.pept.transport.ByteBufferPool;
42
43import com.sun.corba.se.spi.ior.ObjectKey;
44import com.sun.corba.se.spi.ior.ObjectId;
45import com.sun.corba.se.spi.ior.IOR;
46import com.sun.corba.se.spi.ior.ObjectKeyFactory;
47import com.sun.corba.se.spi.ior.iiop.IIOPProfile;
48import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
49import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
50import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
51import com.sun.corba.se.spi.ior.iiop.RequestPartitioningComponent;
52import com.sun.corba.se.spi.logging.CORBALogDomains ;
53import com.sun.corba.se.spi.orb.ORB;
54import com.sun.corba.se.spi.transport.CorbaConnection;
55import com.sun.corba.se.spi.transport.ReadTimeouts;
56
57import com.sun.corba.se.spi.servicecontext.ServiceContexts;
58import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
59import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
60import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
61import com.sun.corba.se.impl.orbutil.ORBUtility;
62import com.sun.corba.se.impl.orbutil.ORBConstants;
63import com.sun.corba.se.impl.protocol.AddressingDispositionException;
64
65import sun.corba.SharedSecrets;
66
67/**
68 * This class acts as the base class for the various GIOP message types. This
69 * also serves as a factory to create various message types. We currently
70 * support GIOP 1.0, 1.1 and 1.2 message types.
71 *
72 * @author Ram Jeyaraman 05/14/2000
73 */
74
75public abstract class MessageBase implements Message{
76
77    // This is only used when the giopDebug flag is
78    // turned on.
79    public byte[] giopHeader;
80    private ByteBuffer byteBuffer;
81    private int threadPoolToUse;
82
83    // (encodingVersion == 0x00) implies CDR encoding,
84    // (encodingVersion >  0x00) implies Java serialization version.
85    byte encodingVersion = (byte) Message.CDR_ENC_VERSION;
86
87    private static ORBUtilSystemException wrapper =
88        ORBUtilSystemException.get( CORBALogDomains.RPC_PROTOCOL ) ;
89
90    // Static methods
91
92    public static String typeToString(int type)
93    {
94        return typeToString((byte)type);
95    }
96
97    public static String typeToString(byte type)
98    {
99        String result = type + "/";
100        switch (type) {
101        case GIOPRequest         : result += "GIOPRequest";         break;
102        case GIOPReply           : result += "GIOPReply";           break;
103        case GIOPCancelRequest   : result += "GIOPCancelRequest";   break;
104        case GIOPLocateRequest   : result += "GIOPLocateRequest";   break;
105        case GIOPLocateReply     : result += "GIOPLocateReply";     break;
106        case GIOPCloseConnection : result += "GIOPCloseConnection"; break;
107        case GIOPMessageError    : result += "GIOPMessageError";    break;
108        case GIOPFragment        : result += "GIOPFragment";        break;
109        default                  : result += "Unknown";             break;
110        }
111        return result;
112    }
113
114    public static MessageBase readGIOPMessage(ORB orb, CorbaConnection connection)
115    {
116        MessageBase msg = readGIOPHeader(orb, connection);
117        msg = (MessageBase)readGIOPBody(orb, connection, (Message)msg);
118        return msg;
119    }
120
121    public static MessageBase readGIOPHeader(ORB orb, CorbaConnection connection)
122    {
123        MessageBase msg = null;
124        ReadTimeouts readTimeouts =
125                           orb.getORBData().getTransportTCPReadTimeouts();
126
127        ByteBuffer buf = null;
128
129        try {
130            buf = connection.read(GIOPMessageHeaderLength,
131                          0, GIOPMessageHeaderLength,
132                          readTimeouts.get_max_giop_header_time_to_wait());
133        } catch (IOException e) {
134            throw wrapper.ioexceptionWhenReadingConnection(e);
135        }
136
137        if (orb.giopDebugFlag) {
138            // Since this is executed in debug mode only the overhead of
139            // using a View Buffer is not an issue. We'll also use a
140            // read-only View Buffer so we don't disturb the state of
141            // byteBuffer.
142            dprint(".readGIOPHeader: " + typeToString(buf.get(7)));
143            dprint(".readGIOPHeader: GIOP header is: ");
144            ByteBuffer viewBuffer = buf.asReadOnlyBuffer();
145            viewBuffer.position(0).limit(GIOPMessageHeaderLength);
146            ByteBufferWithInfo bbwi = new ByteBufferWithInfo(orb,viewBuffer);
147            bbwi.buflen = GIOPMessageHeaderLength;
148            CDRInputStream_1_0.printBuffer(bbwi);
149        }
150
151        // Sanity checks
152
153        /*
154         * check for magic corruption
155         * check for version incompatibility
156         * check if fragmentation is allowed based on mesg type.
157            . 1.0 fragmentation disallowed; FragmentMessage is non-existent.
158            . 1.1 only {Request, Reply} msgs maybe fragmented.
159            . 1.2 only {Request, Reply, LocateRequest, LocateReply} msgs
160              maybe fragmented.
161        */
162
163        int b1, b2, b3, b4;
164
165        b1 = (buf.get(0) << 24) & 0xFF000000;
166        b2 = (buf.get(1) << 16) & 0x00FF0000;
167        b3 = (buf.get(2) << 8)  & 0x0000FF00;
168        b4 = (buf.get(3) << 0)  & 0x000000FF;
169        int magic = (b1 | b2 | b3 | b4);
170
171        if (magic != GIOPBigMagic) {
172            // If Magic is incorrect, it is an error.
173            // ACTION : send MessageError and close the connection.
174            throw wrapper.giopMagicError( CompletionStatus.COMPLETED_MAYBE);
175        }
176
177        // Extract the encoding version from the request GIOP Version,
178        // if it contains an encoding, and set GIOP version appropriately.
179        // For Java serialization, we use GIOP Version 1.2 message format.
180        byte requestEncodingVersion = Message.CDR_ENC_VERSION;
181        if ((buf.get(4) == 0x0D) &&
182            (buf.get(5) <= Message.JAVA_ENC_VERSION) &&
183            (buf.get(5) > Message.CDR_ENC_VERSION) &&
184            orb.getORBData().isJavaSerializationEnabled()) {
185            // Entering this block means the request is using Java encoding,
186            // and the encoding version is <= this ORB's Java encoding version.
187            requestEncodingVersion = buf.get(5);
188            buf.put(4, (byte) 0x01);
189            buf.put(5, (byte) 0x02);
190        }
191
192        GIOPVersion orbVersion = orb.getORBData().getGIOPVersion();
193
194        if (orb.giopDebugFlag) {
195            dprint(".readGIOPHeader: Message GIOP version: "
196                              + buf.get(4) + '.' + buf.get(5));
197            dprint(".readGIOPHeader: ORB Max GIOP Version: "
198                              + orbVersion);
199        }
200
201        if ( (buf.get(4) > orbVersion.getMajor()) ||
202             ( (buf.get(4) == orbVersion.getMajor()) && (buf.get(5) > orbVersion.getMinor()) )
203            ) {
204            // For requests, sending ORB should use the version info
205            // published in the IOR or may choose to use a <= version
206            // for requests. If the version is greater than published version,
207            // it is an error.
208
209            // For replies, the ORB should always receive a version it supports
210            // or less, but never greater (except for MessageError)
211
212            // ACTION : Send back a MessageError() with the the highest version
213            // the server ORB supports, and close the connection.
214            if ( buf.get(7) != GIOPMessageError ) {
215                throw wrapper.giopVersionError( CompletionStatus.COMPLETED_MAYBE);
216            }
217        }
218
219        AreFragmentsAllowed(buf.get(4), buf.get(5), buf.get(6), buf.get(7));
220
221        // create appropriate messages types
222
223        switch (buf.get(7)) {
224
225        case GIOPRequest:
226            if (orb.giopDebugFlag) {
227                dprint(".readGIOPHeader: creating RequestMessage");
228            }
229            //msg = new RequestMessage(orb.giopDebugFlag);
230            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
231                msg = new RequestMessage_1_0(orb);
232            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
233                msg = new RequestMessage_1_1(orb);
234            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
235                msg = new RequestMessage_1_2(orb);
236            } else {
237                throw wrapper.giopVersionError(
238                    CompletionStatus.COMPLETED_MAYBE);
239            }
240            break;
241
242        case GIOPLocateRequest:
243            if (orb.giopDebugFlag) {
244                dprint(".readGIOPHeader: creating LocateRequestMessage");
245            }
246            //msg = new LocateRequestMessage(orb.giopDebugFlag);
247            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
248                msg = new LocateRequestMessage_1_0(orb);
249            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
250                msg = new LocateRequestMessage_1_1(orb);
251            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
252                msg = new LocateRequestMessage_1_2(orb);
253            } else {
254                throw wrapper.giopVersionError(
255                    CompletionStatus.COMPLETED_MAYBE);
256            }
257            break;
258
259        case GIOPCancelRequest:
260            if (orb.giopDebugFlag) {
261                dprint(".readGIOPHeader: creating CancelRequestMessage");
262            }
263            //msg = new CancelRequestMessage(orb.giopDebugFlag);
264            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
265                msg = new CancelRequestMessage_1_0();
266            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
267                msg = new CancelRequestMessage_1_1();
268            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
269                msg = new CancelRequestMessage_1_2();
270            } else {
271                throw wrapper.giopVersionError(
272                    CompletionStatus.COMPLETED_MAYBE);
273            }
274            break;
275
276        case GIOPReply:
277            if (orb.giopDebugFlag) {
278                dprint(".readGIOPHeader: creating ReplyMessage");
279            }
280            //msg = new ReplyMessage(orb.giopDebugFlag);
281            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
282                msg = new ReplyMessage_1_0(orb);
283            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
284                msg = new ReplyMessage_1_1(orb);
285            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
286                msg = new ReplyMessage_1_2(orb);
287            } else {
288                throw wrapper.giopVersionError(
289                    CompletionStatus.COMPLETED_MAYBE);
290            }
291            break;
292
293        case GIOPLocateReply:
294            if (orb.giopDebugFlag) {
295                dprint(".readGIOPHeader: creating LocateReplyMessage");
296            }
297            //msg = new LocateReplyMessage(orb.giopDebugFlag);
298            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
299                msg = new LocateReplyMessage_1_0(orb);
300            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
301                msg = new LocateReplyMessage_1_1(orb);
302            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
303                msg = new LocateReplyMessage_1_2(orb);
304            } else {
305                throw wrapper.giopVersionError(
306                    CompletionStatus.COMPLETED_MAYBE);
307            }
308            break;
309
310        case GIOPCloseConnection:
311        case GIOPMessageError:
312            if (orb.giopDebugFlag) {
313                dprint(".readGIOPHeader: creating Message for CloseConnection or MessageError");
314            }
315            // REVISIT a MessageError  may contain the highest version server
316            // can support. In such a case, a new request may be made with the
317            // correct version or the connection be simply closed. Note the
318            // connection may have been closed by the server.
319            //msg = new Message(orb.giopDebugFlag);
320            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
321                msg = new Message_1_0();
322            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
323                msg = new Message_1_1();
324            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
325                msg = new Message_1_1();
326            } else {
327                throw wrapper.giopVersionError(
328                    CompletionStatus.COMPLETED_MAYBE);
329            }
330            break;
331
332        case GIOPFragment:
333            if (orb.giopDebugFlag) {
334                dprint(".readGIOPHeader: creating FragmentMessage");
335            }
336            //msg = new FragmentMessage(orb.giopDebugFlag);
337            if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
338                // not possible (error checking done already)
339            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x01) ) { // 1.1
340                msg = new FragmentMessage_1_1();
341            } else if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x02) ) { // 1.2
342                msg = new FragmentMessage_1_2();
343            } else {
344                throw wrapper.giopVersionError(
345                    CompletionStatus.COMPLETED_MAYBE);
346            }
347            break;
348
349        default:
350            if (orb.giopDebugFlag)
351                dprint(".readGIOPHeader: UNKNOWN MESSAGE TYPE: "
352                       + buf.get(7));
353            // unknown message type ?
354            // ACTION : send MessageError and close the connection
355            throw wrapper.giopVersionError(
356                CompletionStatus.COMPLETED_MAYBE);
357        }
358
359        //
360        // Initialize the generic GIOP header instance variables.
361        //
362
363        if ( (buf.get(4) == 0x01) && (buf.get(5) == 0x00) ) { // 1.0
364            Message_1_0 msg10 = (Message_1_0) msg;
365            msg10.magic = magic;
366            msg10.GIOP_version = new GIOPVersion(buf.get(4), buf.get(5));
367            msg10.byte_order = (buf.get(6) == LITTLE_ENDIAN_BIT);
368            // 'request partitioning' not supported on GIOP version 1.0
369            // so just use the default thread pool, 0.
370            msg.threadPoolToUse = 0;
371            msg10.message_type = buf.get(7);
372            msg10.message_size = readSize(buf.get(8), buf.get(9), buf.get(10), buf.get(11),
373                                          msg10.isLittleEndian()) +
374                                 GIOPMessageHeaderLength;
375        } else { // 1.1 & 1.2
376            Message_1_1 msg11 = (Message_1_1) msg;
377            msg11.magic = magic;
378            msg11.GIOP_version = new GIOPVersion(buf.get(4), buf.get(5));
379            msg11.flags = (byte)(buf.get(6) & TRAILING_TWO_BIT_BYTE_MASK);
380            // IMPORTANT: For 'request partitioning', the thread pool to use
381            //            information is stored in the leading 6 bits of byte 6.
382            //
383            // IMPORTANT: Request partitioning is a PROPRIETARY EXTENSION !!!
384            //
385            // NOTE: Bitwise operators will promote a byte to an int before
386            //       performing a bitwise operation and bytes, ints, longs, etc
387            //       are signed types in Java. Thus, the need for the
388            //       THREAD_POOL_TO_USE_MASK operation.
389            msg.threadPoolToUse = (buf.get(6) >>> 2) & THREAD_POOL_TO_USE_MASK;
390            msg11.message_type = buf.get(7);
391            msg11.message_size =
392                      readSize(buf.get(8), buf.get(9), buf.get(10), buf.get(11),
393                              msg11.isLittleEndian()) + GIOPMessageHeaderLength;
394        }
395
396
397        if (orb.giopDebugFlag) {
398            // Since this is executed in debug mode only the overhead of
399            // using a View Buffer is not an issue. We'll also use a
400            // read-only View Buffer so we don't disturb the state of
401            // byteBuffer.
402            dprint(".readGIOPHeader: header construction complete.");
403
404            // For debugging purposes, save the 12 bytes of the header
405            ByteBuffer viewBuf = buf.asReadOnlyBuffer();
406            byte[] msgBuf = new byte[GIOPMessageHeaderLength];
407            viewBuf.position(0).limit(GIOPMessageHeaderLength);
408            viewBuf.get(msgBuf,0,msgBuf.length);
409            // REVISIT: is giopHeader still used?
410            ((MessageBase)msg).giopHeader = msgBuf;
411        }
412
413        msg.setByteBuffer(buf);
414        msg.setEncodingVersion(requestEncodingVersion);
415
416        return msg;
417    }
418
419    public static Message readGIOPBody(ORB orb,
420                                       CorbaConnection connection,
421                                       Message msg)
422    {
423        ReadTimeouts readTimeouts =
424                           orb.getORBData().getTransportTCPReadTimeouts();
425        ByteBuffer buf = msg.getByteBuffer();
426
427        buf.position(MessageBase.GIOPMessageHeaderLength);
428        int msgSizeMinusHeader =
429            msg.getSize() - MessageBase.GIOPMessageHeaderLength;
430        try {
431            buf = connection.read(buf,
432                          GIOPMessageHeaderLength, msgSizeMinusHeader,
433                          readTimeouts.get_max_time_to_wait());
434        } catch (IOException e) {
435            throw wrapper.ioexceptionWhenReadingConnection(e);
436        }
437
438        msg.setByteBuffer(buf);
439
440        if (orb.giopDebugFlag) {
441            dprint(".readGIOPBody: received message:");
442            ByteBuffer viewBuffer = buf.asReadOnlyBuffer();
443            viewBuffer.position(0).limit(msg.getSize());
444            ByteBufferWithInfo bbwi = new ByteBufferWithInfo(orb, viewBuffer);
445            CDRInputStream_1_0.printBuffer(bbwi);
446        }
447
448        return msg;
449    }
450
451    private static RequestMessage createRequest(
452            ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
453            boolean response_expected, byte[] object_key, String operation,
454            ServiceContexts service_contexts, Principal requesting_principal) {
455
456        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
457            return new RequestMessage_1_0(orb, service_contexts, request_id,
458                                         response_expected, object_key,
459                                         operation, requesting_principal);
460        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
461            return new RequestMessage_1_1(orb, service_contexts, request_id,
462                response_expected, new byte[] { 0x00, 0x00, 0x00 },
463                object_key, operation, requesting_principal);
464        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
465            // Note: Currently we use response_expected flag to decide if the
466            // call is oneway or not. Ideally, it is possible to expect a
467            // response on a oneway call too, but we do not support it now.
468            byte response_flags = 0x03;
469            if (response_expected) {
470                response_flags = 0x03;
471            } else {
472                response_flags = 0x00;
473            }
474            /*
475            // REVISIT The following is the correct way to do it. This gives
476            // more flexibility.
477            if ((DII::INV_NO_RESPONSE == false) && response_expected) {
478                response_flags = 0x03; // regular two-way
479            } else if ((DII::INV_NO_RESPONSE == false) && !response_expected) {
480                // this condition is not possible
481            } else if ((DII::INV_NO_RESPONSE == true) && response_expected) {
482                // oneway, but we need response for LocationForwards or
483                // SystemExceptions.
484                response_flags = 0x01;
485            } else if ((DII::INV_NO_RESPONSE == true) && !response_expected) {
486                // oneway, no response required
487                response_flags = 0x00;
488            }
489            */
490            TargetAddress target = new TargetAddress();
491            target.object_key(object_key);
492            RequestMessage msg =
493                new RequestMessage_1_2(orb, request_id, response_flags,
494                                       new byte[] { 0x00, 0x00, 0x00 },
495                                       target, operation, service_contexts);
496            msg.setEncodingVersion(encodingVersion);
497            return msg;
498        } else {
499            throw wrapper.giopVersionError(
500                CompletionStatus.COMPLETED_MAYBE);
501        }
502    }
503
504    public static RequestMessage createRequest(
505            ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
506            boolean response_expected, IOR ior,
507            short addrDisp, String operation,
508            ServiceContexts service_contexts, Principal requesting_principal) {
509
510        RequestMessage requestMessage = null;
511        IIOPProfile profile = ior.getProfile();
512
513        if (addrDisp == KeyAddr.value) {
514            // object key will be used for target addressing
515            profile = ior.getProfile();
516            ObjectKey objKey = profile.getObjectKey();
517            byte[] object_key = objKey.getBytes(orb);
518            requestMessage =
519                   createRequest(orb, gv, encodingVersion, request_id,
520                                 response_expected, object_key,
521                                 operation, service_contexts,
522                                 requesting_principal);
523        } else {
524
525            if (!(gv.equals(GIOPVersion.V1_2))) {
526                // only object_key based target addressing is allowed for
527                // GIOP 1.0 & 1.1
528                throw wrapper.giopVersionError(
529                    CompletionStatus.COMPLETED_MAYBE);
530            }
531
532            // Note: Currently we use response_expected flag to decide if the
533            // call is oneway or not. Ideally, it is possible to expect a
534            // response on a oneway call too, but we do not support it now.
535            byte response_flags = 0x03;
536            if (response_expected) {
537                response_flags = 0x03;
538            } else {
539                response_flags = 0x00;
540            }
541
542            TargetAddress target = new TargetAddress();
543            if (addrDisp == ProfileAddr.value) { // iop profile will be used
544                profile = ior.getProfile();
545                target.profile(profile.getIOPProfile());
546            } else if (addrDisp == ReferenceAddr.value) {  // ior will be used
547                IORAddressingInfo iorInfo =
548                    new IORAddressingInfo( 0, // profile index
549                        ior.getIOPIOR());
550                target.ior(iorInfo);
551            } else {
552                // invalid target addressing disposition value
553                throw wrapper.illegalTargetAddressDisposition(
554                    CompletionStatus.COMPLETED_NO);
555            }
556
557            requestMessage =
558                   new RequestMessage_1_2(orb, request_id, response_flags,
559                                  new byte[] { 0x00, 0x00, 0x00 }, target,
560                                  operation, service_contexts);
561            requestMessage.setEncodingVersion(encodingVersion);
562        }
563
564        if (gv.supportsIORIIOPProfileComponents()) {
565            // add request partitioning thread pool to use info
566            int poolToUse = 0; // default pool
567            IIOPProfileTemplate temp =
568                (IIOPProfileTemplate)profile.getTaggedProfileTemplate();
569            Iterator iter =
570                temp.iteratorById(ORBConstants.TAG_REQUEST_PARTITIONING_ID);
571            if (iter.hasNext()) {
572                poolToUse =
573                    ((RequestPartitioningComponent)iter.next()).getRequestPartitioningId();
574            }
575
576            if (poolToUse < ORBConstants.REQUEST_PARTITIONING_MIN_THREAD_POOL_ID ||
577                poolToUse > ORBConstants.REQUEST_PARTITIONING_MAX_THREAD_POOL_ID) {
578                throw wrapper.invalidRequestPartitioningId(new Integer(poolToUse),
579                      new Integer(ORBConstants.REQUEST_PARTITIONING_MIN_THREAD_POOL_ID),
580                      new Integer(ORBConstants.REQUEST_PARTITIONING_MAX_THREAD_POOL_ID));
581            }
582            requestMessage.setThreadPoolToUse(poolToUse);
583        }
584
585        return requestMessage;
586    }
587
588    public static ReplyMessage createReply(
589            ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
590            int reply_status, ServiceContexts service_contexts, IOR ior) {
591
592        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
593            return new ReplyMessage_1_0(orb, service_contexts, request_id,
594                                        reply_status, ior);
595        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
596            return new ReplyMessage_1_1(orb, service_contexts, request_id,
597                                        reply_status, ior);
598        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
599            ReplyMessage msg =
600                new ReplyMessage_1_2(orb, request_id, reply_status,
601                                     service_contexts, ior);
602            msg.setEncodingVersion(encodingVersion);
603            return msg;
604        } else {
605            throw wrapper.giopVersionError(
606                CompletionStatus.COMPLETED_MAYBE);
607        }
608    }
609
610    public static LocateRequestMessage createLocateRequest(
611            ORB orb, GIOPVersion gv, byte encodingVersion,
612            int request_id, byte[] object_key) {
613
614        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
615            return new LocateRequestMessage_1_0(orb, request_id, object_key);
616        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
617            return new LocateRequestMessage_1_1(orb, request_id, object_key);
618        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
619            TargetAddress target = new TargetAddress();
620            target.object_key(object_key);
621            LocateRequestMessage msg =
622                new LocateRequestMessage_1_2(orb, request_id, target);
623            msg.setEncodingVersion(encodingVersion);
624            return msg;
625        } else {
626            throw wrapper.giopVersionError(
627                CompletionStatus.COMPLETED_MAYBE);
628        }
629    }
630
631    public static LocateReplyMessage createLocateReply(
632            ORB orb, GIOPVersion gv, byte encodingVersion,
633            int request_id, int locate_status, IOR ior) {
634
635        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
636            return new LocateReplyMessage_1_0(orb, request_id,
637                                              locate_status, ior);
638        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
639            return new LocateReplyMessage_1_1(orb, request_id,
640                                              locate_status, ior);
641        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
642            LocateReplyMessage msg =
643                new LocateReplyMessage_1_2(orb, request_id,
644                                           locate_status, ior);
645            msg.setEncodingVersion(encodingVersion);
646            return msg;
647        } else {
648            throw wrapper.giopVersionError(
649                CompletionStatus.COMPLETED_MAYBE);
650        }
651    }
652
653    public static CancelRequestMessage createCancelRequest(
654            GIOPVersion gv, int request_id) {
655
656        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
657            return new CancelRequestMessage_1_0(request_id);
658        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
659            return new CancelRequestMessage_1_1(request_id);
660        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
661            return new CancelRequestMessage_1_2(request_id);
662        } else {
663            throw wrapper.giopVersionError(
664                CompletionStatus.COMPLETED_MAYBE);
665        }
666    }
667
668    public static Message createCloseConnection(GIOPVersion gv) {
669        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
670            return new Message_1_0(Message.GIOPBigMagic, false,
671                                   Message.GIOPCloseConnection, 0);
672        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
673            return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_1,
674                                   FLAG_NO_FRAG_BIG_ENDIAN,
675                                   Message.GIOPCloseConnection, 0);
676        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
677            return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_2,
678                                   FLAG_NO_FRAG_BIG_ENDIAN,
679                                   Message.GIOPCloseConnection, 0);
680        } else {
681            throw wrapper.giopVersionError(
682                CompletionStatus.COMPLETED_MAYBE);
683        }
684    }
685
686    public static Message createMessageError(GIOPVersion gv) {
687        if (gv.equals(GIOPVersion.V1_0)) { // 1.0
688            return new Message_1_0(Message.GIOPBigMagic, false,
689                                   Message.GIOPMessageError, 0);
690        } else if (gv.equals(GIOPVersion.V1_1)) { // 1.1
691            return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_1,
692                                   FLAG_NO_FRAG_BIG_ENDIAN,
693                                   Message.GIOPMessageError, 0);
694        } else if (gv.equals(GIOPVersion.V1_2)) { // 1.2
695            return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_2,
696                                   FLAG_NO_FRAG_BIG_ENDIAN,
697                                   Message.GIOPMessageError, 0);
698        } else {
699            throw wrapper.giopVersionError(
700                CompletionStatus.COMPLETED_MAYBE);
701        }
702    }
703
704    public static FragmentMessage createFragmentMessage(GIOPVersion gv) {
705        // This method is not currently used.
706        // New fragment messages are always created from existing messages.
707        // Creating a FragmentMessage from InputStream is done in
708        // createFromStream(..)
709        return null;
710    }
711
712    public static int getRequestId(Message msg) {
713        switch (msg.getType()) {
714        case GIOPRequest :
715            return ((RequestMessage) msg).getRequestId();
716        case GIOPReply :
717            return ((ReplyMessage) msg).getRequestId();
718        case GIOPLocateRequest :
719            return ((LocateRequestMessage) msg).getRequestId();
720        case GIOPLocateReply :
721            return ((LocateReplyMessage) msg).getRequestId();
722        case GIOPCancelRequest :
723            return ((CancelRequestMessage) msg).getRequestId();
724        case GIOPFragment :
725            return ((FragmentMessage) msg).getRequestId();
726        }
727
728        throw wrapper.illegalGiopMsgType(
729            CompletionStatus.COMPLETED_MAYBE);
730    }
731
732    /**
733     * Set a flag in the given buffer (fragment bit, byte order bit, etc)
734     */
735    public static void setFlag(ByteBuffer byteBuffer, int flag) {
736        byte b = byteBuffer.get(6);
737        b |= flag;
738        byteBuffer.put(6,b);
739    }
740
741    /**
742     * Clears a flag in the given buffer
743     */
744    public static void clearFlag(byte[] buf, int flag) {
745        buf[6] &= (0xFF ^ flag);
746    }
747
748    private static void AreFragmentsAllowed(byte major, byte minor, byte flag,
749            byte msgType) {
750
751        if ( (major == 0x01) && (minor == 0x00) ) { // 1.0
752            if (msgType == GIOPFragment) {
753                throw wrapper.fragmentationDisallowed(
754                    CompletionStatus.COMPLETED_MAYBE);
755            }
756        }
757
758        if ( (flag & MORE_FRAGMENTS_BIT) == MORE_FRAGMENTS_BIT ) {
759            switch (msgType) {
760            case GIOPCancelRequest :
761            case GIOPCloseConnection :
762            case GIOPMessageError :
763                throw wrapper.fragmentationDisallowed(
764                    CompletionStatus.COMPLETED_MAYBE);
765            case GIOPLocateRequest :
766            case GIOPLocateReply :
767                if ( (major == 0x01) && (minor == 0x01) ) { // 1.1
768                    throw wrapper.fragmentationDisallowed(
769                        CompletionStatus.COMPLETED_MAYBE);
770                }
771                break;
772            }
773        }
774    }
775
776    /**
777     * Construct an ObjectKey from a byte[].
778     *
779     * @return ObjectKey the object key.
780     */
781    static ObjectKey extractObjectKey(byte[] objKey, ORB orb) {
782
783        try {
784            if (objKey != null) {
785                ObjectKey objectKey =
786                    orb.getObjectKeyFactory().create(objKey);
787                if (objectKey != null) {
788                    return objectKey;
789                }
790            }
791        } catch (Exception e) {
792            // XXX log this exception
793        }
794
795        // This exception is thrown if any exceptions are raised while
796        // extracting the object key or if the object key is empty.
797        throw wrapper.invalidObjectKey();
798    }
799
800    /**
801     * Extract the object key from TargetAddress.
802     *
803     * @return ObjectKey the object key.
804     */
805    static ObjectKey extractObjectKey(TargetAddress target, ORB orb) {
806
807        short orbTargetAddrPref = orb.getORBData().getGIOPTargetAddressPreference();
808        short reqAddrDisp = target.discriminator();
809
810        switch (orbTargetAddrPref) {
811        case ORBConstants.ADDR_DISP_OBJKEY :
812            if (reqAddrDisp != KeyAddr.value) {
813                throw new AddressingDispositionException(KeyAddr.value);
814            }
815            break;
816        case ORBConstants.ADDR_DISP_PROFILE :
817            if (reqAddrDisp != ProfileAddr.value) {
818                throw new AddressingDispositionException(ProfileAddr.value);
819            }
820            break;
821        case ORBConstants.ADDR_DISP_IOR :
822            if (reqAddrDisp != ReferenceAddr.value) {
823                throw new AddressingDispositionException(ReferenceAddr.value);
824            }
825            break;
826        case ORBConstants.ADDR_DISP_HANDLE_ALL :
827            break;
828        default :
829            throw wrapper.orbTargetAddrPreferenceInExtractObjectkeyInvalid() ;
830        }
831
832        try {
833            switch (reqAddrDisp) {
834            case KeyAddr.value :
835                byte[] objKey = target.object_key();
836                if (objKey != null) { // AddressingDisposition::KeyAddr
837                    ObjectKey objectKey =
838                        orb.getObjectKeyFactory().create(objKey);
839                    if (objectKey != null) {
840                       return objectKey;
841                   }
842                }
843                break;
844            case ProfileAddr.value :
845                IIOPProfile iiopProfile = null;
846                TaggedProfile profile = target.profile();
847                if (profile != null) { // AddressingDisposition::ProfileAddr
848                   iiopProfile = IIOPFactories.makeIIOPProfile(orb, profile);
849                   ObjectKey objectKey = iiopProfile.getObjectKey();
850                   if (objectKey != null) {
851                       return objectKey;
852                   }
853                }
854                break;
855            case ReferenceAddr.value :
856                IORAddressingInfo iorInfo = target.ior();
857                if (iorInfo != null) { // AddressingDisposition::IORAddr
858                    profile = iorInfo.ior.profiles[iorInfo.selected_profile_index];
859                    iiopProfile = IIOPFactories.makeIIOPProfile(orb, profile);
860                    ObjectKey objectKey = iiopProfile.getObjectKey();
861                    if (objectKey != null) {
862                       return objectKey;
863                   }
864                }
865                break;
866            default : // this cannot happen
867                // There is no need for a explicit exception, since the
868                // TargetAddressHelper.read() would have raised a BAD_OPERATION
869                // exception by now.
870                break;
871            }
872        } catch (Exception e) {}
873
874        // This exception is thrown if any exceptions are raised while
875        // extracting the object key from the TargetAddress or if all the
876        // the valid TargetAddress::AddressingDispositions are empty.
877        throw wrapper.invalidObjectKey() ;
878    }
879
880    private static int readSize(byte b1, byte b2, byte b3, byte b4,
881            boolean littleEndian) {
882
883        int a1, a2, a3, a4;
884
885        if (!littleEndian) {
886            a1 = (b1 << 24) & 0xFF000000;
887            a2 = (b2 << 16) & 0x00FF0000;
888            a3 = (b3 << 8)  & 0x0000FF00;
889            a4 = (b4 << 0)  & 0x000000FF;
890        } else {
891            a1 = (b4 << 24) & 0xFF000000;
892            a2 = (b3 << 16) & 0x00FF0000;
893            a3 = (b2 << 8)  & 0x0000FF00;
894            a4 = (b1 << 0)  & 0x000000FF;
895        }
896
897        return (a1 | a2 | a3 | a4);
898    }
899
900    static void nullCheck(Object obj) {
901        if (obj == null) {
902            throw wrapper.nullNotAllowed() ;
903        }
904    }
905
906    static SystemException getSystemException(
907        String exClassName, int minorCode, CompletionStatus completionStatus,
908        String message, ORBUtilSystemException wrapper)
909    {
910        SystemException sysEx = null;
911
912        try {
913            Class<?> clazz =
914                SharedSecrets.getJavaCorbaAccess().loadClass(exClassName);
915            if (message == null) {
916                sysEx = (SystemException) clazz.newInstance();
917            } else {
918                Class[] types = { String.class };
919                Constructor constructor = clazz.getConstructor(types);
920                Object[] args = { message };
921                sysEx = (SystemException)constructor.newInstance(args);
922            }
923        } catch (Exception someEx) {
924            throw wrapper.badSystemExceptionInReply(
925                CompletionStatus.COMPLETED_MAYBE, someEx );
926        }
927
928        sysEx.minor = minorCode;
929        sysEx.completed = completionStatus;
930
931        return sysEx;
932    }
933
934    public void callback(MessageHandler handler)
935        throws java.io.IOException
936    {
937        handler.handleInput(this);
938    }
939
940    public ByteBuffer getByteBuffer()
941    {
942        return byteBuffer;
943    }
944
945    public void setByteBuffer(ByteBuffer byteBuffer)
946    {
947        this.byteBuffer = byteBuffer;
948    }
949
950    public int getThreadPoolToUse()
951    {
952        return threadPoolToUse;
953    }
954
955    public byte getEncodingVersion() {
956        return this.encodingVersion;
957    }
958
959    public void setEncodingVersion(byte version) {
960        this.encodingVersion = version;
961    }
962
963    private static void dprint(String msg)
964    {
965        ORBUtility.dprint("MessageBase", msg);
966    }
967}
968