package org.jacorb.orb.giop;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jacorb.orb.CDROutputStream;
import org.jacorb.orb.CodeSet;
import org.jacorb.orb.miop.MIOPProfile;
import org.jacorb.orb.miop.MulticastUtil;
import org.jacorb.util.Time;
import org.omg.CONV_FRAME.CodeSetContext;
import org.omg.CONV_FRAME.CodeSetContextHelper;
import org.omg.CORBA.MARSHAL;
import org.omg.GIOP.PrincipalHelper;
import org.omg.GIOP.MsgType_1_1;
import org.omg.GIOP.TargetAddress;
import org.omg.GIOP.TargetAddressHelper;
import org.omg.IOP.INVOCATION_POLICIES;
import org.omg.IOP.ServiceContext;
import org.omg.IOP.ServiceContextListHelper;
import org.omg.IOP.TAG_CODE_SETS;
import org.omg.IOP.TAG_UIPMC;
import org.omg.IOP.TaggedProfile;
import org.omg.MIOP.UIPMC_ProfileBodyHelper;
import org.omg.Messaging.PolicyValue;
import org.omg.Messaging.PolicyValueSeqHelper;
import org.omg.Messaging.REPLY_END_TIME_POLICY_TYPE;
import org.omg.Messaging.REQUEST_END_TIME_POLICY_TYPE;
import org.omg.Messaging.REQUEST_START_TIME_POLICY_TYPE;
import org.omg.Messaging.SYNC_NONE;
import org.omg.Messaging.SYNC_WITH_SERVER;
import org.omg.Messaging.SYNC_WITH_TARGET;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
import org.omg.TimeBase.UtcT;
/**
* @author Gerald Brose, FU Berlin 1999
*/
public class RequestOutputStream
extends ServiceContextTransportingOutputStream
{
private final static byte[] principal = new byte[ 0 ];
private final static byte[] reserved = new byte[ 3 ];
private final int request_id;
private final boolean response_expected;
private final short syncScope;
private final String operation;
/**
* Absolute time after which this request may be delivered to its target.
* (CORBA 3.0, 22.2.4.1)
*/
private final UtcT requestStartTime;
/**
* Absolute time after which this request may no longer be delivered
* to its target. (CORBA 3.0, 22.2.4.2/5)
*/
private final UtcT requestEndTime;
/**
* Absolute time after which a reply may no longer be obtained
* or returned to the client. (CORBA 3.0, 22.2.4.4/6)
*/
private final UtcT replyEndTime;
private org.jacorb.orb.dii.Request request = null;
private final ClientConnection connection;
private final byte[] object_key;
/**
* Copy constructor for <code>RequestOutputStream</code> used for SYNC_SCOPE NONE.
*
* @param other a <code>RequestOutputStream</code> value
*/
public RequestOutputStream( RequestOutputStream other)
{
super(other.orb);
this.object_key = other.object_key;
this.request_id = other.request_id;
this.response_expected = other.response_expected;
this.syncScope = other.syncScope;
this.operation = other.operation;
this.connection = other.connection;
this.requestStartTime = other.requestStartTime;
this.requestEndTime = other.requestEndTime;
this.replyEndTime = other.replyEndTime;
this.contexts = other.contexts;
this.header_end = other.header_end;
this.header_padding = other.header_padding;
this.giop_minor = other.giop_minor;
byte[] copy = other.getBufferCopy();
write_octet_array (copy, 0, copy.length);
}
public RequestOutputStream( org.jacorb.orb.ORB orb,
ClientConnection connection,
int request_id,
String operation,
boolean response_expected,
short syncScope,
UtcT requestStartTime,
UtcT requestEndTime,
UtcT replyEndTime,
byte[] object_key, int giop_minor )
{
super(orb);
setGIOPMinor( giop_minor );
this.object_key = object_key;
this.request_id = request_id;
this.response_expected = response_expected;
this.syncScope = syncScope;
this.operation = operation;
this.connection = connection;
this.requestStartTime = requestStartTime;
this.requestEndTime = requestEndTime;
this.replyEndTime = replyEndTime;
if (requestStartTime != null ||
requestEndTime != null ||
replyEndTime != null)
{
addServiceContext (createInvocationPolicies());
}
writeGIOPMsgHeader( MsgType_1_1._Request,
giop_minor );
boolean isMIOP = (connection != null && connection.getRegisteredProfile () instanceof MIOPProfile);
switch( giop_minor )
{
case 0 :
case 1 :
{
//GIOP 1.0/1.1 inlined
ServiceContextListHelper.write( this , Messages.service_context );
write_ulong( request_id);
write_boolean( response_expected );
if (giop_minor == 1)
{
write_octet_array( reserved,0,3 );
}
if (isMIOP)
{
write_char_array (MulticastUtil.MAGIC, 0, MulticastUtil.MAGIC.length);
write_long (TAG_UIPMC.value);
this.beginEncapsulation ();
UIPMC_ProfileBodyHelper.write (this, ((MIOPProfile)connection.getRegisteredProfile ()).getUIPMCProfile ());
this.endEncapsulation ();
}
else
{
write_long( object_key.length );
write_octet_array( object_key, 0, object_key.length);
}
write_string( operation);
PrincipalHelper.write( this, principal);
break;
}
case 2 :
{
//GIOP 1.2
TargetAddress addr = new TargetAddress();
if (isMIOP)
{
TaggedProfile uipmc = new TaggedProfile (org.omg.IOP.TAG_UIPMC.value, MulticastUtil.getEncapsulatedUIPMCProfile (orb, connection));
addr.profile (uipmc);
}
else
{
addr.object_key( object_key );
}
// inlined RequestHeader_1_2Helper.write method
write_ulong( request_id);
if (response_expected)
{
write_octet ((byte)0x03);
}
else
{
switch (syncScope)
{
case SYNC_NONE.value:
// fallthrough
case SYNC_WITH_TRANSPORT.value:
{
write_octet ((byte)0x00);
break;
}
case SYNC_WITH_SERVER.value:
{
write_octet ((byte)0x01);
break;
}
case SYNC_WITH_TARGET.value:
{
write_octet ((byte)0x03);
break;
}
default:
{
throw new MARSHAL ("Invalid SYNC_SCOPE: " + syncScope);
}
}
}
write_octet_array( reserved,0,3 );
TargetAddressHelper.write( this, addr );
write_string( operation );
ServiceContextListHelper.write( this, Messages.service_context );
markHeaderEnd(); //use padding if GIOP minor == 2
break;
}
default :
{
throw new MARSHAL( "Unknown GIOP minor: " + giop_minor );
}
}
}
public int requestId()
{
return request_id;
}
public boolean response_expected()
{
return response_expected;
}
public short syncScope()
{
return syncScope;
}
public String operation()
{
return operation;
}
public UtcT getReplyEndTime()
{
return replyEndTime;
}
public void setRequest(org.jacorb.orb.dii.Request request)
{
this.request = request;
}
public org.jacorb.orb.dii.Request getRequest()
{
return request;
}
public ClientConnection getConnection()
{
return connection;
}
/**
* Overridden to add a codeset service context if this
* is the first request on the connection.
*/
public void write_to(GIOPConnection conn) throws IOException
{
if (!conn.isTCSNegotiated())
{
// encapsulate context
addServiceContext (createCodesetContext ( conn.getTCS(), conn.getTCSW()));
conn.markTCSNegotiated();
}
super.write_to(conn);
}
private ServiceContext createCodesetContext( CodeSet tcs, CodeSet tcsw )
{
// encapsulate context
final CDROutputStream os = new CDROutputStream( orb );
try
{
os.beginEncapsulatedArray();
CodeSetContextHelper.write( os, new CodeSetContext( tcs.getId(), tcsw.getId() ));
return new ServiceContext( TAG_CODE_SETS.value, os.getBufferCopy() );
}
finally
{
os.close();
}
}
/**
* Returns the timing policies for this request as an array
* of PolicyValues that can be propagated in a ServiceContext.
*/
private PolicyValue[] getTimingPolicyValues()
{
List list = new ArrayList();
if (requestStartTime != null)
{
list.add (new PolicyValue (REQUEST_START_TIME_POLICY_TYPE.value,
Time.toCDR (requestStartTime)));
}
if (requestEndTime != null)
{
list.add (new PolicyValue (REQUEST_END_TIME_POLICY_TYPE.value,
Time.toCDR (requestEndTime)));
}
if (replyEndTime != null)
{
list.add (new PolicyValue (REPLY_END_TIME_POLICY_TYPE.value,
Time.toCDR (replyEndTime)));
}
return (PolicyValue[])list.toArray (new PolicyValue[list.size()]);
}
private ServiceContext createInvocationPolicies()
{
final CDROutputStream out = new CDROutputStream( orb );
try
{
out.beginEncapsulatedArray();
PolicyValueSeqHelper.write(out, getTimingPolicyValues());
return new ServiceContext (INVOCATION_POLICIES.value,
out.getBufferCopy());
}
finally
{
out.close();
}
}
}