/*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.jboss.com.sun.corba.se.impl.protocol.giopmsgheaders;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.ByteBuffer;
import java.util.Iterator;
import org.jboss.com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
import org.jboss.com.sun.corba.se.impl.encoding.CDRInputStream_1_0;
import org.jboss.com.sun.corba.se.impl.logging.ORBUtilSystemException;
import org.jboss.com.sun.corba.se.impl.orbutil.ORBClassLoader;
import org.jboss.com.sun.corba.se.impl.orbutil.ORBConstants;
import org.jboss.com.sun.corba.se.impl.orbutil.ORBUtility;
import org.jboss.com.sun.corba.se.impl.protocol.AddressingDispositionException;
import org.jboss.com.sun.corba.se.spi.ior.IOR;
import org.jboss.com.sun.corba.se.spi.ior.ObjectKey;
import org.jboss.com.sun.corba.se.spi.ior.iiop.GIOPVersion;
import org.jboss.com.sun.corba.se.spi.ior.iiop.IIOPFactories;
import org.jboss.com.sun.corba.se.spi.ior.iiop.IIOPProfile;
import org.jboss.com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate;
import org.jboss.com.sun.corba.se.spi.ior.iiop.RequestPartitioningComponent;
import org.jboss.com.sun.corba.se.spi.logging.CORBALogDomains;
import org.jboss.com.sun.corba.se.spi.orb.ORB;
import org.jboss.com.sun.corba.se.spi.servicecontext.ServiceContexts;
import org.jboss.com.sun.corba.se.spi.transport.CorbaConnection;
import org.jboss.com.sun.corba.se.spi.transport.ReadTimeouts;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.Principal;
import org.omg.CORBA.SystemException;
import org.omg.IOP.TaggedProfile;
/**
* This class acts as the base class for the various GIOP message types. This also serves as a factory to create various
* message types. We currently support GIOP 1.0, 1.1 and 1.2 message types.
*
* @author Ram Jeyaraman 05/14/2000
*/
@SuppressWarnings("deprecation")
public abstract class MessageBase implements Message
{
// This is only used when the giopDebug flag is
// turned on.
public byte[] giopHeader;
private ByteBuffer byteBuffer;
private int threadPoolToUse;
// (encodingVersion == 0x00) implies CDR encoding,
// (encodingVersion > 0x00) implies Java serialization version.
byte encodingVersion = Message.CDR_ENC_VERSION;
private static ORBUtilSystemException wrapper = ORBUtilSystemException.get(CORBALogDomains.RPC_PROTOCOL);
// Static methods
public static String typeToString(int type)
{
return typeToString((byte) type);
}
public static String typeToString(byte type)
{
String result = type + "/";
switch (type)
{
case GIOPRequest :
result += "GIOPRequest";
break;
case GIOPReply :
result += "GIOPReply";
break;
case GIOPCancelRequest :
result += "GIOPCancelRequest";
break;
case GIOPLocateRequest :
result += "GIOPLocateRequest";
break;
case GIOPLocateReply :
result += "GIOPLocateReply";
break;
case GIOPCloseConnection :
result += "GIOPCloseConnection";
break;
case GIOPMessageError :
result += "GIOPMessageError";
break;
case GIOPFragment :
result += "GIOPFragment";
break;
default :
result += "Unknown";
break;
}
return result;
}
public static MessageBase readGIOPMessage(ORB orb, CorbaConnection connection)
{
MessageBase msg = readGIOPHeader(orb, connection);
msg = (MessageBase) readGIOPBody(orb, connection, msg);
return msg;
}
public static MessageBase readGIOPHeader(ORB orb, CorbaConnection connection)
{
MessageBase msg = null;
ReadTimeouts readTimeouts = orb.getORBData().getTransportTCPReadTimeouts();
ByteBuffer buf = null;
try
{
buf = connection.read(GIOPMessageHeaderLength, 0, GIOPMessageHeaderLength,
readTimeouts.get_max_giop_header_time_to_wait());
}
catch (IOException e)
{
throw wrapper.ioexceptionWhenReadingConnection(e);
}
if (orb.giopDebugFlag)
{
// Since this is executed in debug mode only the overhead of using a View Buffer is not an issue. We'll also
// use a read-only View Buffer so we don't disturb the state of byteBuffer.
dprint(".readGIOPHeader: " + typeToString(buf.get(7)));
dprint(".readGIOPHeader: GIOP header is: ");
ByteBuffer viewBuffer = buf.asReadOnlyBuffer();
viewBuffer.position(0).limit(GIOPMessageHeaderLength);
ByteBufferWithInfo bbwi = new ByteBufferWithInfo(orb, viewBuffer);
bbwi.buflen = GIOPMessageHeaderLength;
CDRInputStream_1_0.printBuffer(bbwi);
}
// Sanity checks
/*
* check for magic corruption check for version incompatibility check if fragmentation is allowed based on mesg
* type. . 1.0 fragmentation disallowed; FragmentMessage is non-existent. . 1.1 only {Request, Reply} msgs maybe
* fragmented. . 1.2 only {Request, Reply, LocateRequest, LocateReply} msgs maybe fragmented.
*/
int b1, b2, b3, b4;
b1 = (buf.get(0) << 24) & 0xFF000000;
b2 = (buf.get(1) << 16) & 0x00FF0000;
b3 = (buf.get(2) << 8) & 0x0000FF00;
b4 = (buf.get(3) << 0) & 0x000000FF;
int magic = (b1 | b2 | b3 | b4);
if (magic != GIOPBigMagic)
{
// If Magic is incorrect, it is an error.
// ACTION : send MessageError and close the connection.
throw wrapper.giopMagicError(CompletionStatus.COMPLETED_MAYBE);
}
// Extract the encoding version from the request GIOP Version, if it contains an encoding, and set GIOP version
// appropriately. For Java serialization, we use GIOP Version 1.2 message format.
byte requestEncodingVersion = Message.CDR_ENC_VERSION;
if ((buf.get(4) == 0x0D) && (buf.get(5) <= Message.JAVA_ENC_VERSION) && (buf.get(5) > Message.CDR_ENC_VERSION)
&& orb.getORBData().isJavaSerializationEnabled())
{
// Entering this block means the request is using Java encoding, and the encoding version is <= this ORB's
// Java encoding version.
requestEncodingVersion = buf.get(5);
buf.put(4, (byte) 0x01);
buf.put(5, (byte) 0x02);
}
GIOPVersion orbVersion = orb.getORBData().getGIOPVersion();
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: Message GIOP version: " + buf.get(4) + '.' + buf.get(5));
dprint(".readGIOPHeader: ORB Max GIOP Version: " + orbVersion);
}
if ((buf.get(4) > orbVersion.getMajor())
|| ((buf.get(4) == orbVersion.getMajor()) && (buf.get(5) > orbVersion.getMinor())))
{
// For requests, sending ORB should use the version info published in the IOR or may choose to use a <=
// version for requests. If the version is greater than published version, it is an error.
// For replies, the ORB should always receive a version it supports or less, but never greater (except for
// MessageError)
// ACTION : Send back a MessageError() with the the highest version the server ORB supports, and close the
// connection.
if (buf.get(7) != GIOPMessageError)
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
AreFragmentsAllowed(buf.get(4), buf.get(5), buf.get(6), buf.get(7));
// create appropriate messages types
switch (buf.get(7))
{
case GIOPRequest :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating RequestMessage");
}
// msg = new RequestMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new RequestMessage_1_0(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new RequestMessage_1_1(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new RequestMessage_1_2(orb);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPLocateRequest :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating LocateRequestMessage");
}
// msg = new LocateRequestMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new LocateRequestMessage_1_0(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new LocateRequestMessage_1_1(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new LocateRequestMessage_1_2(orb);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPCancelRequest :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating CancelRequestMessage");
}
// msg = new CancelRequestMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new CancelRequestMessage_1_0();
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new CancelRequestMessage_1_1();
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new CancelRequestMessage_1_2();
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPReply :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating ReplyMessage");
}
// msg = new ReplyMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new ReplyMessage_1_0(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new ReplyMessage_1_1(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new ReplyMessage_1_2(orb);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPLocateReply :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating LocateReplyMessage");
}
// msg = new LocateReplyMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new LocateReplyMessage_1_0(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new LocateReplyMessage_1_1(orb);
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new LocateReplyMessage_1_2(orb);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPCloseConnection :
case GIOPMessageError :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating Message for CloseConnection or MessageError");
}
// REVISIT a MessageError may contain the highest version server can support. In such a case, a new
// request may be made with the correct version or the connection be simply closed. Note the connection
// may have been closed by the server. msg = new Message(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
msg = new Message_1_0();
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new Message_1_1();
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new Message_1_1();
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
case GIOPFragment :
if (orb.giopDebugFlag)
{
dprint(".readGIOPHeader: creating FragmentMessage");
}
// msg = new FragmentMessage(orb.giopDebugFlag);
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
// not possible (error checking done already)
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x01))
{ // 1.1
msg = new FragmentMessage_1_1();
}
else if ((buf.get(4) == 0x01) && (buf.get(5) == 0x02))
{ // 1.2
msg = new FragmentMessage_1_2();
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
break;
default :
if (orb.giopDebugFlag)
dprint(".readGIOPHeader: UNKNOWN MESSAGE TYPE: " + buf.get(7));
// unknown message type ?
// ACTION : send MessageError and close the connection
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
//
// Initialize the generic GIOP header instance variables.
//
if ((buf.get(4) == 0x01) && (buf.get(5) == 0x00))
{ // 1.0
Message_1_0 msg10 = (Message_1_0) msg;
msg10.magic = magic;
msg10.GIOP_version = new GIOPVersion(buf.get(4), buf.get(5));
msg10.byte_order = (buf.get(6) == LITTLE_ENDIAN_BIT);
// 'request partitioning' not supported on GIOP version 1.0
// so just use the default thread pool, 0.
msg.threadPoolToUse = 0;
msg10.message_type = buf.get(7);
msg10.message_size = readSize(buf.get(8), buf.get(9), buf.get(10), buf.get(11), msg10.isLittleEndian())
+ GIOPMessageHeaderLength;
}
else
{ // 1.1 & 1.2
Message_1_1 msg11 = (Message_1_1) msg;
msg11.magic = magic;
msg11.GIOP_version = new GIOPVersion(buf.get(4), buf.get(5));
msg11.flags = (byte) (buf.get(6) & TRAILING_TWO_BIT_BYTE_MASK);
// IMPORTANT: For 'request partitioning', the thread pool to use information is stored in the leading 6 bits
// of byte 6.
//
// IMPORTANT: Request partitioning is a PROPRIETARY EXTENSION !!!
//
// NOTE: Bitwise operators will promote a byte to an int before performing a bitwise operation and bytes,
// ints, longs, etc are signed types in Java. Thus, the need for the THREAD_POOL_TO_USE_MASK operation.
msg.threadPoolToUse = (buf.get(6) >>> 2) & THREAD_POOL_TO_USE_MASK;
msg11.message_type = buf.get(7);
msg11.message_size = readSize(buf.get(8), buf.get(9), buf.get(10), buf.get(11), msg11.isLittleEndian())
+ GIOPMessageHeaderLength;
}
if (orb.giopDebugFlag)
{
// Since this is executed in debug mode only the overhead of using a View Buffer is not an issue. We'll also
// use a read-only View Buffer so we don't disturb the state of byteBuffer.
dprint(".readGIOPHeader: header construction complete.");
// For debugging purposes, save the 12 bytes of the header
ByteBuffer viewBuf = buf.asReadOnlyBuffer();
byte[] msgBuf = new byte[GIOPMessageHeaderLength];
viewBuf.position(0).limit(GIOPMessageHeaderLength);
viewBuf.get(msgBuf, 0, msgBuf.length);
// REVISIT: is giopHeader still used?
msg.giopHeader = msgBuf;
}
msg.setByteBuffer(buf);
msg.setEncodingVersion(requestEncodingVersion);
return msg;
}
public static Message readGIOPBody(ORB orb, CorbaConnection connection, Message msg)
{
ReadTimeouts readTimeouts = orb.getORBData().getTransportTCPReadTimeouts();
ByteBuffer buf = msg.getByteBuffer();
buf.position(MessageBase.GIOPMessageHeaderLength);
int msgSizeMinusHeader = msg.getSize() - MessageBase.GIOPMessageHeaderLength;
try
{
buf = connection
.read(buf, GIOPMessageHeaderLength, msgSizeMinusHeader, readTimeouts.get_max_time_to_wait());
}
catch (IOException e)
{
throw wrapper.ioexceptionWhenReadingConnection(e);
}
msg.setByteBuffer(buf);
if (orb.giopDebugFlag)
{
dprint(".readGIOPBody: received message:");
ByteBuffer viewBuffer = buf.asReadOnlyBuffer();
viewBuffer.position(0).limit(msg.getSize());
ByteBufferWithInfo bbwi = new ByteBufferWithInfo(orb, viewBuffer);
CDRInputStream_1_0.printBuffer(bbwi);
}
return msg;
}
private static RequestMessage createRequest(ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
boolean response_expected, byte[] object_key, String operation, ServiceContexts service_contexts,
Principal requesting_principal)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new RequestMessage_1_0(orb, service_contexts, request_id, response_expected, object_key, operation,
requesting_principal);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new RequestMessage_1_1(orb, service_contexts, request_id, response_expected, new byte[]{0x00, 0x00,
0x00}, object_key, operation, requesting_principal);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
// Note: Currently we use response_expected flag to decide if the call is oneway or not. Ideally, it is
// possible to expect a response on a oneway call too, but we do not support it now.
byte response_flags = 0x03;
if (response_expected)
{
response_flags = 0x03;
}
else
{
response_flags = 0x00;
}
/*
* // REVISIT The following is the correct way to do it. This gives // more flexibility. if
* ((DII::INV_NO_RESPONSE == false) && response_expected) { response_flags = 0x03; // regular two-way } else
* if ((DII::INV_NO_RESPONSE == false) && !response_expected) { // this condition is not possible } else if
* ((DII::INV_NO_RESPONSE == true) && response_expected) { // oneway, but we need response for
* LocationForwards or // SystemExceptions. response_flags = 0x01; } else if ((DII::INV_NO_RESPONSE == true)
* && !response_expected) { // oneway, no response required response_flags = 0x00; }
*/
TargetAddress target = new TargetAddress();
target.object_key(object_key);
RequestMessage msg = new RequestMessage_1_2(orb, request_id, response_flags, new byte[]{0x00, 0x00, 0x00},
target, operation, service_contexts);
msg.setEncodingVersion(encodingVersion);
return msg;
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static RequestMessage 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)
{
RequestMessage requestMessage = null;
IIOPProfile profile = ior.getProfile();
if (addrDisp == KeyAddr.value)
{
// object key will be used for target addressing
profile = ior.getProfile();
ObjectKey objKey = profile.getObjectKey();
byte[] object_key = objKey.getBytes(orb);
requestMessage = createRequest(orb, gv, encodingVersion, request_id, response_expected, object_key,
operation, service_contexts, requesting_principal);
}
else
{
if (!(gv.equals(GIOPVersion.V1_2)))
{
// only object_key based target addressing is allowed for
// GIOP 1.0 & 1.1
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
// Note: Currently we use response_expected flag to decide if the call is oneway or not. Ideally, it is
// possible to expect a response on a oneway call too, but we do not support it now.
byte response_flags = 0x03;
if (response_expected)
{
response_flags = 0x03;
}
else
{
response_flags = 0x00;
}
TargetAddress target = new TargetAddress();
if (addrDisp == ProfileAddr.value)
{ // iop profile will be used
profile = ior.getProfile();
target.profile(profile.getIOPProfile());
}
else if (addrDisp == ReferenceAddr.value)
{ // ior will be used
IORAddressingInfo iorInfo = new IORAddressingInfo(0, // profile index
ior.getIOPIOR());
target.ior(iorInfo);
}
else
{
// invalid target addressing disposition value
throw wrapper.illegalTargetAddressDisposition(CompletionStatus.COMPLETED_NO);
}
requestMessage = new RequestMessage_1_2(orb, request_id, response_flags, new byte[]{0x00, 0x00, 0x00},
target, operation, service_contexts);
requestMessage.setEncodingVersion(encodingVersion);
}
if (gv.supportsIORIIOPProfileComponents())
{
// add request partitioning thread pool to use info
int poolToUse = 0; // default pool
IIOPProfileTemplate temp = (IIOPProfileTemplate) profile.getTaggedProfileTemplate();
Iterator<Object> iter = temp.iteratorById(ORBConstants.TAG_REQUEST_PARTITIONING_ID);
if (iter.hasNext())
{
poolToUse = ((RequestPartitioningComponent) iter.next()).getRequestPartitioningId();
}
if (poolToUse < ORBConstants.REQUEST_PARTITIONING_MIN_THREAD_POOL_ID
|| poolToUse > ORBConstants.REQUEST_PARTITIONING_MAX_THREAD_POOL_ID)
{
throw wrapper.invalidRequestPartitioningId(new Integer(poolToUse), new Integer(
ORBConstants.REQUEST_PARTITIONING_MIN_THREAD_POOL_ID), new Integer(
ORBConstants.REQUEST_PARTITIONING_MAX_THREAD_POOL_ID));
}
requestMessage.setThreadPoolToUse(poolToUse);
}
return requestMessage;
}
public static ReplyMessage createReply(ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
int reply_status, ServiceContexts service_contexts, IOR ior)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new ReplyMessage_1_0(orb, service_contexts, request_id, reply_status, ior);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new ReplyMessage_1_1(orb, service_contexts, request_id, reply_status, ior);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
ReplyMessage msg = new ReplyMessage_1_2(orb, request_id, reply_status, service_contexts, ior);
msg.setEncodingVersion(encodingVersion);
return msg;
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static LocateRequestMessage createLocateRequest(ORB orb, GIOPVersion gv, byte encodingVersion,
int request_id, byte[] object_key)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new LocateRequestMessage_1_0(orb, request_id, object_key);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new LocateRequestMessage_1_1(orb, request_id, object_key);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
TargetAddress target = new TargetAddress();
target.object_key(object_key);
LocateRequestMessage msg = new LocateRequestMessage_1_2(orb, request_id, target);
msg.setEncodingVersion(encodingVersion);
return msg;
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static LocateReplyMessage createLocateReply(ORB orb, GIOPVersion gv, byte encodingVersion, int request_id,
int locate_status, IOR ior)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new LocateReplyMessage_1_0(orb, request_id, locate_status, ior);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new LocateReplyMessage_1_1(orb, request_id, locate_status, ior);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
LocateReplyMessage msg = new LocateReplyMessage_1_2(orb, request_id, locate_status, ior);
msg.setEncodingVersion(encodingVersion);
return msg;
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static CancelRequestMessage createCancelRequest(GIOPVersion gv, int request_id)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new CancelRequestMessage_1_0(request_id);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new CancelRequestMessage_1_1(request_id);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
return new CancelRequestMessage_1_2(request_id);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static Message createCloseConnection(GIOPVersion gv)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new Message_1_0(Message.GIOPBigMagic, false, Message.GIOPCloseConnection, 0);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_1, FLAG_NO_FRAG_BIG_ENDIAN,
Message.GIOPCloseConnection, 0);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_2, FLAG_NO_FRAG_BIG_ENDIAN,
Message.GIOPCloseConnection, 0);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static Message createMessageError(GIOPVersion gv)
{
if (gv.equals(GIOPVersion.V1_0))
{ // 1.0
return new Message_1_0(Message.GIOPBigMagic, false, Message.GIOPMessageError, 0);
}
else if (gv.equals(GIOPVersion.V1_1))
{ // 1.1
return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_1, FLAG_NO_FRAG_BIG_ENDIAN,
Message.GIOPMessageError, 0);
}
else if (gv.equals(GIOPVersion.V1_2))
{ // 1.2
return new Message_1_1(Message.GIOPBigMagic, GIOPVersion.V1_2, FLAG_NO_FRAG_BIG_ENDIAN,
Message.GIOPMessageError, 0);
}
else
{
throw wrapper.giopVersionError(CompletionStatus.COMPLETED_MAYBE);
}
}
public static FragmentMessage createFragmentMessage(GIOPVersion gv)
{
// This method is not currently used. New fragment messages are always created from existing messages. Creating
// a FragmentMessage from InputStream is done in createFromStream(..)
return null;
}
public static int getRequestId(Message msg)
{
switch (msg.getType())
{
case GIOPRequest :
return ((RequestMessage) msg).getRequestId();
case GIOPReply :
return ((ReplyMessage) msg).getRequestId();
case GIOPLocateRequest :
return ((LocateRequestMessage) msg).getRequestId();
case GIOPLocateReply :
return ((LocateReplyMessage) msg).getRequestId();
case GIOPCancelRequest :
return ((CancelRequestMessage) msg).getRequestId();
case GIOPFragment :
return ((FragmentMessage) msg).getRequestId();
}
throw wrapper.illegalGiopMsgType(CompletionStatus.COMPLETED_MAYBE);
}
/**
* Set a flag in the given buffer (fragment bit, byte order bit, etc)
*/
public static void setFlag(ByteBuffer byteBuffer, int flag)
{
byte b = byteBuffer.get(6);
b |= flag;
byteBuffer.put(6, b);
}
/**
* Clears a flag in the given buffer
*/
public static void clearFlag(byte[] buf, int flag)
{
buf[6] &= (0xFF ^ flag);
}
private static void AreFragmentsAllowed(byte major, byte minor, byte flag, byte msgType)
{
if ((major == 0x01) && (minor == 0x00))
{ // 1.0
if (msgType == GIOPFragment)
{
throw wrapper.fragmentationDisallowed(CompletionStatus.COMPLETED_MAYBE);
}
}
if ((flag & MORE_FRAGMENTS_BIT) == MORE_FRAGMENTS_BIT)
{
switch (msgType)
{
case GIOPCancelRequest :
case GIOPCloseConnection :
case GIOPMessageError :
throw wrapper.fragmentationDisallowed(CompletionStatus.COMPLETED_MAYBE);
case GIOPLocateRequest :
case GIOPLocateReply :
if ((major == 0x01) && (minor == 0x01))
{ // 1.1
throw wrapper.fragmentationDisallowed(CompletionStatus.COMPLETED_MAYBE);
}
break;
}
}
}
/**
* Construct an ObjectKey from a byte[].
*
* @return ObjectKey the object key.
*/
static ObjectKey extractObjectKey(byte[] objKey, ORB orb)
{
try
{
if (objKey != null)
{
ObjectKey objectKey = orb.getObjectKeyFactory().create(objKey);
if (objectKey != null)
{
return objectKey;
}
}
}
catch (Exception e)
{
// XXX log this exception
}
// This exception is thrown if any exceptions are raised while
// extracting the object key or if the object key is empty.
throw wrapper.invalidObjectKey();
}
/**
* Extract the object key from TargetAddress.
*
* @return ObjectKey the object key.
*/
static ObjectKey extractObjectKey(TargetAddress target, ORB orb)
{
short orbTargetAddrPref = orb.getORBData().getGIOPTargetAddressPreference();
short reqAddrDisp = target.discriminator();
switch (orbTargetAddrPref)
{
case ORBConstants.ADDR_DISP_OBJKEY :
if (reqAddrDisp != KeyAddr.value)
{
throw new AddressingDispositionException(KeyAddr.value);
}
break;
case ORBConstants.ADDR_DISP_PROFILE :
if (reqAddrDisp != ProfileAddr.value)
{
throw new AddressingDispositionException(ProfileAddr.value);
}
break;
case ORBConstants.ADDR_DISP_IOR :
if (reqAddrDisp != ReferenceAddr.value)
{
throw new AddressingDispositionException(ReferenceAddr.value);
}
break;
case ORBConstants.ADDR_DISP_HANDLE_ALL :
break;
default :
throw wrapper.orbTargetAddrPreferenceInExtractObjectkeyInvalid();
}
try
{
switch (reqAddrDisp)
{
case KeyAddr.value :
byte[] objKey = target.object_key();
if (objKey != null)
{ // AddressingDisposition::KeyAddr
ObjectKey objectKey = orb.getObjectKeyFactory().create(objKey);
if (objectKey != null)
{
return objectKey;
}
}
break;
case ProfileAddr.value :
IIOPProfile iiopProfile = null;
TaggedProfile profile = target.profile();
if (profile != null)
{ // AddressingDisposition::ProfileAddr
iiopProfile = IIOPFactories.makeIIOPProfile(orb, profile);
ObjectKey objectKey = iiopProfile.getObjectKey();
if (objectKey != null)
{
return objectKey;
}
}
break;
case ReferenceAddr.value :
IORAddressingInfo iorInfo = target.ior();
if (iorInfo != null)
{ // AddressingDisposition::IORAddr
profile = iorInfo.ior.profiles[iorInfo.selected_profile_index];
iiopProfile = IIOPFactories.makeIIOPProfile(orb, profile);
ObjectKey objectKey = iiopProfile.getObjectKey();
if (objectKey != null)
{
return objectKey;
}
}
break;
default : // this cannot happen
// There is no need for a explicit exception, since the TargetAddressHelper.read() would have raised
// a BAD_OPERATION exception by now.
break;
}
}
catch (Exception e)
{
}
// This exception is thrown if any exceptions are raised while extracting the object key from the TargetAddress
// or if all the the valid TargetAddress::AddressingDispositions are empty.
throw wrapper.invalidObjectKey();
}
private static int readSize(byte b1, byte b2, byte b3, byte b4, boolean littleEndian)
{
int a1, a2, a3, a4;
if (!littleEndian)
{
a1 = (b1 << 24) & 0xFF000000;
a2 = (b2 << 16) & 0x00FF0000;
a3 = (b3 << 8) & 0x0000FF00;
a4 = (b4 << 0) & 0x000000FF;
}
else
{
a1 = (b4 << 24) & 0xFF000000;
a2 = (b3 << 16) & 0x00FF0000;
a3 = (b2 << 8) & 0x0000FF00;
a4 = (b1 << 0) & 0x000000FF;
}
return (a1 | a2 | a3 | a4);
}
static void nullCheck(Object obj)
{
if (obj == null)
{
throw wrapper.nullNotAllowed();
}
}
static SystemException getSystemException(String exClassName, int minorCode, CompletionStatus completionStatus,
String message, ORBUtilSystemException wrapper)
{
SystemException sysEx = null;
try
{
Class<?> clazz = ORBClassLoader.loadClass(exClassName);
if (message == null)
{
sysEx = (SystemException) clazz.newInstance();
}
else
{
Class<?>[] types = {String.class};
Constructor<?> constructor = clazz.getConstructor(types);
Object[] args = {message};
sysEx = (SystemException) constructor.newInstance(args);
}
}
catch (Exception someEx)
{
throw wrapper.badSystemExceptionInReply(CompletionStatus.COMPLETED_MAYBE, someEx);
}
sysEx.minor = minorCode;
sysEx.completed = completionStatus;
return sysEx;
}
public void callback(MessageHandler handler) throws java.io.IOException
{
handler.handleInput(this);
}
public ByteBuffer getByteBuffer()
{
return byteBuffer;
}
public void setByteBuffer(ByteBuffer byteBuffer)
{
this.byteBuffer = byteBuffer;
}
public int getThreadPoolToUse()
{
return threadPoolToUse;
}
public byte getEncodingVersion()
{
return this.encodingVersion;
}
public void setEncodingVersion(byte version)
{
this.encodingVersion = version;
}
private static void dprint(String msg)
{
ORBUtility.dprint("MessageBase", msg);
}
}