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 
  26 package com.sun.corba.se.impl.protocol.giopmsgheaders;
  27 
  28 import java.io.IOException;
  29 import java.lang.Class;
  30 import java.lang.reflect.Constructor;
  31 import java.nio.ByteBuffer;
  32 import java.util.Iterator;
  33 
  34 import org.omg.CORBA.CompletionStatus;
  35 import org.omg.CORBA.INTERNAL;
  36 import org.omg.CORBA.MARSHAL;
  37 import org.omg.CORBA.Principal;
  38 import org.omg.CORBA.SystemException;
  39 import org.omg.IOP.TaggedProfile;
  40 
  41 import com.sun.corba.se.pept.transport.ByteBufferPool;
  42 
  43 import com.sun.corba.se.spi.ior.ObjectKey;
  44 import com.sun.corba.se.spi.ior.ObjectId;
  45 import com.sun.corba.se.spi.ior.IOR;
  46 import com.sun.corba.se.spi.ior.ObjectKeyFactory;
  47 import com.sun.corba.se.spi.ior.iiop.IIOPProfile;
  48 import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
  49 import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
  50 import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  51 import com.sun.corba.se.spi.ior.iiop.RequestPartitioningComponent;
  52 import com.sun.corba.se.spi.logging.CORBALogDomains ;
  53 import com.sun.corba.se.spi.orb.ORB;
  54 import com.sun.corba.se.spi.transport.CorbaConnection;
  55 import com.sun.corba.se.spi.transport.ReadTimeouts;
  56 
  57 import com.sun.corba.se.spi.servicecontext.ServiceContexts;
  58 import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
  59 import com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
  60 import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  61 import com.sun.corba.se.impl.orbutil.ORBUtility;
  62 import com.sun.corba.se.impl.orbutil.ORBConstants;
  63 import com.sun.corba.se.impl.protocol.AddressingDispositionException;
  64 
  65 import 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 
  75 public 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 }