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 
typeToString(int type)92     public static String typeToString(int type)
93     {
94         return typeToString((byte)type);
95     }
96 
typeToString(byte type)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 
readGIOPMessage(ORB orb, CorbaConnection connection)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 
readGIOPHeader(ORB orb, CorbaConnection connection)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 
readGIOPBody(ORB orb, CorbaConnection connection, Message msg)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 
createRequest( ORB orb, GIOPVersion gv, byte encodingVersion, int request_id, boolean response_expected, byte[] object_key, String operation, ServiceContexts service_contexts, Principal requesting_principal)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 
createRequest( ORB orb, GIOPVersion gv, byte encodingVersion, int request_id, boolean response_expected, IOR ior, short addrDisp, String operation, ServiceContexts service_contexts, Principal requesting_principal)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 
createReply( ORB orb, GIOPVersion gv, byte encodingVersion, int request_id, int reply_status, ServiceContexts service_contexts, IOR ior)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 
createLocateRequest( ORB orb, GIOPVersion gv, byte encodingVersion, int request_id, byte[] object_key)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 
createLocateReply( ORB orb, GIOPVersion gv, byte encodingVersion, int request_id, int locate_status, IOR ior)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 
createCancelRequest( GIOPVersion gv, int request_id)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 
createCloseConnection(GIOPVersion gv)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 
createMessageError(GIOPVersion gv)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 
createFragmentMessage(GIOPVersion gv)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 
getRequestId(Message msg)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      */
setFlag(ByteBuffer byteBuffer, int flag)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      */
clearFlag(byte[] buf, int flag)744     public static void clearFlag(byte[] buf, int flag) {
745         buf[6] &= (0xFF ^ flag);
746     }
747 
AreFragmentsAllowed(byte major, byte minor, byte flag, byte msgType)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      */
extractObjectKey(byte[] objKey, ORB orb)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      */
extractObjectKey(TargetAddress target, ORB orb)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 
readSize(byte b1, byte b2, byte b3, byte b4, boolean littleEndian)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 
nullCheck(Object obj)900     static void nullCheck(Object obj) {
901         if (obj == null) {
902             throw wrapper.nullNotAllowed() ;
903         }
904     }
905 
getSystemException( String exClassName, int minorCode, CompletionStatus completionStatus, String message, ORBUtilSystemException wrapper)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 
callback(MessageHandler handler)934     public void callback(MessageHandler handler)
935         throws java.io.IOException
936     {
937         handler.handleInput(this);
938     }
939 
getByteBuffer()940     public ByteBuffer getByteBuffer()
941     {
942         return byteBuffer;
943     }
944 
setByteBuffer(ByteBuffer byteBuffer)945     public void setByteBuffer(ByteBuffer byteBuffer)
946     {
947         this.byteBuffer = byteBuffer;
948     }
949 
getThreadPoolToUse()950     public int getThreadPoolToUse()
951     {
952         return threadPoolToUse;
953     }
954 
getEncodingVersion()955     public byte getEncodingVersion() {
956         return this.encodingVersion;
957     }
958 
setEncodingVersion(byte version)959     public void setEncodingVersion(byte version) {
960         this.encodingVersion = version;
961     }
962 
dprint(String msg)963     private static void dprint(String msg)
964     {
965         ORBUtility.dprint("MessageBase", msg);
966     }
967 }
968