blob: ad989ced7d0f37c59c42e306508343f76bac4d09 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.yoko.orb.OB;
import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.BooleanHolder;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.NO_RESPONSE;
import org.omg.CORBA.NVList;
import org.omg.CORBA.NamedValue;
import org.omg.CORBA.OBJECT_NOT_EXIST;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Policy;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TRANSIENT;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.UserException;
import org.omg.CORBA.portable.ApplicationException;
import org.omg.CORBA.portable.OutputStream;
import org.omg.CORBA.portable.RemarshalException;
import org.omg.GIOP.MessageHeader_1_1;
import org.omg.GIOP.MessageHeader_1_2Helper;
import org.omg.GIOP.MsgType_1_1;
import org.omg.GIOP.RequestHeader_1_2;
import org.omg.GIOP.RequestHeader_1_2Helper;
import org.omg.IOP.INVOCATION_POLICIES;
import org.omg.IOP.IOR;
import org.omg.IOP.ServiceContext;
import org.omg.IOP.ServiceContextListHolder;
import org.omg.MessageRouting.MessageBody;
import org.omg.MessageRouting.PersistentRequest;
import org.omg.MessageRouting.PersistentRequestRouter;
import org.omg.MessageRouting.ReplyDestination;
import org.omg.MessageRouting.ReplyDisposition;
import org.omg.MessageRouting.RequestInfo;
import org.omg.MessageRouting.RequestMessage;
import org.omg.MessageRouting.Router;
import org.omg.MessageRouting.RouterListHolder;
import org.omg.Messaging.PolicyValue;
import org.omg.Messaging.PolicyValueSeqHelper;
import org.omg.Messaging.PolicyValueSeqHolder;
import org.omg.Messaging.ReplyHandler;
//
// DowncallStub is equivalent to the C++ class OB::MarshalStubImpl
//
public final class DowncallStub {
static final Logger logger = Logger.getLogger(DowncallStub.class.getName());
//
// The ORBInstance object
//
private ORBInstance orbInstance_;
//
// The IOR and the original IOR
//
private IOR IOR_;
private IOR origIOR_;
//
// The list of policies
//
private RefCountPolicyList policies_;
//
// All client/profile pairs
//
private Vector<ClientProfilePair> clientProfilePairs_;
//
// We need a class to carry the DowncallStub and Downcall across
// a portable stub invocation
//
private class InvocationContext {
DowncallStub downcallStub;
Downcall downcall;
}
// ------------------------------------------------------------------
// Private and protected member implementations
// ------------------------------------------------------------------
private synchronized Client getClientProfilePair(org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo)
throws FailureException {
//
// Lazy initialization of the client/profile pairs
//
if (clientProfilePairs_ == null) {
//
// Get all clients that can be used
//
ClientManager clientManager = orbInstance_.getClientManager();
clientProfilePairs_ = clientManager.getClientProfilePairs(IOR_, policies_.value);
}
//
// If we can't get any client/profile pairs, set and raise the
// failure exception, and let the stub handle this.
//
if (clientProfilePairs_.isEmpty()) {
CoreTraceLevels coreTraceLevels = orbInstance_.getCoreTraceLevels();
if (coreTraceLevels.traceRetry() >= 2) {
logger.fine("retry: no profiles available");
}
throw new FailureException(new TRANSIENT(org.apache.yoko.orb.OB.MinorCodes.describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR), org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR, CompletionStatus.COMPLETED_NO));
}
ClientProfilePair clientProfilePair = (ClientProfilePair) clientProfilePairs_.elementAt(0);
profileInfo.value = clientProfilePair.profile;
return clientProfilePair.client;
}
private void destroy(boolean terminate) {
//
// If the ORB has been destroyed then the clientManager can be nil
//
ClientManager clientManager = orbInstance_.getClientManager();
if (clientManager != null && clientProfilePairs_ != null) {
for (ClientProfilePair pair: clientProfilePairs_) {
clientManager.releaseClient(pair.client, terminate);
}
}
clientProfilePairs_.removeAllElements();
}
protected void finalize() throws Throwable {
destroy(false);
super.finalize();
}
// ------------------------------------------------------------------
// Public member implementations
// ------------------------------------------------------------------
public DowncallStub(ORBInstance orbInstance, IOR ior, IOR origIOR, RefCountPolicyList policies) {
clientProfilePairs_ = null;
//
// Save the ORBInstance object
//
orbInstance_ = orbInstance;
//
// Save the IOR
//
IOR_ = ior;
origIOR_ = origIOR;
//
// Save the policies
//
policies_ = policies;
}
//
// Operations to create new Downcall objects
//
public Downcall createDowncall(String op, boolean resp)
throws FailureException {
org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
Client client = getClientProfilePair(profile);
Assert._OB_assert(client != null);
if (!policies_.interceptor) {
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
}
PIManager piManager = orbInstance_.getPIManager();
if (piManager.haveClientInterceptors()) {
return new PIDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager);
} else {
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
}
}
public Downcall createLocateRequestDowncall() throws FailureException {
org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
Client client = getClientProfilePair(profile);
Assert._OB_assert(client != null);
//
// A LocateRequest is not seen by the interceptors
//
return new Downcall(orbInstance_, client, profile.value, policies_, "_locate", true);
}
public Downcall createPIArgsDowncall(String op, boolean resp, ParameterDesc[] argDesc, ParameterDesc retDesc, TypeCode[] exceptionTC) throws FailureException {
org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
Client client = getClientProfilePair(profile);
Assert._OB_assert(client != null);
if (!policies_.interceptor)
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
PIManager piManager = orbInstance_.getPIManager();
if (piManager.haveClientInterceptors()) {
return new PIArgsDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager, argDesc, retDesc, exceptionTC);
} else {
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
}
}
public Downcall createPIDIIDowncall(String op, boolean resp, NVList args, NamedValue result, ExceptionList exceptions) throws FailureException {
org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
Client client = getClientProfilePair(profile);
Assert._OB_assert(client != null);
if (!policies_.interceptor)
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
PIManager piManager = orbInstance_.getPIManager();
if (piManager.haveClientInterceptors()) {
return new PIDIIDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager, args, result, exceptions);
} else {
return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
}
}
//
// Marshalling interception points
//
public org.apache.yoko.orb.CORBA.OutputStream preMarshal(Downcall down) throws LocationForward, FailureException {
return down.preMarshal();
}
public void marshalEx(Downcall down, SystemException ex) throws LocationForward, FailureException {
down.marshalEx(ex);
}
public void postMarshal(Downcall down) throws LocationForward, FailureException {
down.postMarshal();
}
//
// Methods to invoke requests and pick up replies
//
public void locate(Downcall down) throws LocationForward, FailureException {
down.locate();
}
public void request(Downcall down) throws LocationForward, FailureException {
down.request();
}
public void oneway(Downcall down) throws LocationForward, FailureException {
down.oneway();
}
public void deferred(Downcall down) throws LocationForward, FailureException {
down.deferred();
}
public void response(Downcall down) throws LocationForward, FailureException {
down.response();
}
public boolean poll(Downcall down) throws LocationForward, FailureException {
return down.poll();
}
//
// Unmarshalling interception points
//
public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down) throws LocationForward, FailureException {
return down.preUnmarshal();
}
public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down, BooleanHolder uex) throws LocationForward, FailureException {
org.apache.yoko.orb.CORBA.InputStream in = down.preUnmarshal();
uex.value = down.userException();
return in;
}
public void unmarshalEx(Downcall down, SystemException ex) throws LocationForward, FailureException {
down.unmarshalEx(ex);
}
public void postUnmarshal(Downcall down) throws LocationForward, FailureException {
down.postUnmarshal();
}
//
// Operations for handling user exceptions
//
public String unmarshalExceptionId(Downcall down) {
return down.unmarshalExceptionId();
}
public void setUserException(Downcall down, UserException ex, String exId) {
down.setUserException(ex, exId);
}
public void setUserException(Downcall down, UserException ex) {
down.setUserException(ex);
}
//
// Handle a FailureException
//
public synchronized void handleFailureException(Downcall down, FailureException ex) throws FailureException {
//
// Only called if there is really a failure
//
Assert._OB_assert(ex.exception != null);
//
// If there was a failure, release the client and remove the
// faulty client/profile pair, whether we retry or not
//
Client client = down.client();
org.apache.yoko.orb.OCI.ProfileInfo profile = down.profileInfo();
final ClientManager clientManager = orbInstance_.getClientManager();
//
// Make sure the ORB has not been destroyed
//
if (clientManager == null)
throw new BAD_INV_ORDER(
MinorCodes.describeBadInvOrder(
org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled,
CompletionStatus.COMPLETED_NO);
for (ClientProfilePair pair : clientProfilePairs_) {
if (pair.client == client && pair.profile == profile) {
clientManager.releaseClient(pair.client, false);
clientProfilePairs_.remove(pair);
break;
}
}
//
// We only retry upon COMM_FAILURE, TRANSIENT, and NO_RESPONSE
//
try {
throw ex.exception;
} catch (COMM_FAILURE|TRANSIENT|NO_RESPONSE forceRetry) {
} catch (SystemException systemException) {
throw ex; // Not "throw e;"!
}
//
// We can't retry if RETRY_STRICT or RETRY_NEVER is set and the
// completion status is not COMPLETED_NO
//
if (policies_.retry.mode != RETRY_ALWAYS.value && ex.exception.completed != CompletionStatus.COMPLETED_NO) {
throw ex;
}
//
// If no client/profile pairs are left, we cannot retry either
//
if (clientProfilePairs_.isEmpty()) {
logger.log(Level.FINE, "no profiles left to try", ex.exception);
throw ex;
}
//
// OK, let's continue with the next profile
//
logger.log(Level.FINE, "trying next profile", ex.exception);
}
public boolean locate_request() throws LocationForward, FailureException {
logger.fine("performing a locate_request");
while (true) {
org.apache.yoko.orb.OB.Downcall down = createLocateRequestDowncall();
try {
try {
//
// Get the client and force a binding
//
Client client = down.client();
client.bind(policies_.connectTimeout);
//
// If the LocateRequest policy is false, then return now
//
if (!policies_.locateRequest) {
logger.fine("LocateRequest policy is false, returning true");
return true;
}
//
// If the client doesn't support twoway invocations,
// then silently pretend the locate request succeeded
//
if (!client.twoway()) {
logger.fine("Twoway invocations not supported, returning true");
return true;
}
} catch (SystemException ex) {
logger.log(Level.FINE, "Exception occurred during locate request", ex);
throw new FailureException(ex);
}
preMarshal(down);
postMarshal(down);
locate(down);
preUnmarshal(down);
postUnmarshal(down);
logger.fine("Object located");
return true;
} catch (OBJECT_NOT_EXIST ex) {
logger.log(Level.FINE, "Object does not exist", ex);
return false;
} catch (FailureException ex) {
logger.log(Level.FINE, "Object lookup failure", ex);
handleFailureException(down, ex);
}
}
}
public org.apache.yoko.orb.OCI.ConnectorInfo get_oci_connector_info() {
try {
org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
org.apache.yoko.orb.OB.Client client = getClientProfilePair(profileInfo);
org.apache.yoko.orb.OB.Assert._OB_assert(client != null);
return client.connectorInfo();
} catch (org.apache.yoko.orb.OB.FailureException ex) {
Assert._OB_assert(ex);
return null; // The compiler needs this
}
}
public org.apache.yoko.orb.OCI.TransportInfo get_oci_transport_info() {
try {
org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
org.apache.yoko.orb.OB.Client client = getClientProfilePair(profileInfo);
org.apache.yoko.orb.OB.Assert._OB_assert(client != null);
return client.transportInfo();
} catch (org.apache.yoko.orb.OB.FailureException ex) {
Assert._OB_assert(ex);
return null; // The compiler needs this
}
}
//
// Prepare a request from a portable stub
//
public org.apache.yoko.orb.CORBA.OutputStream setupRequest(
org.omg.CORBA.Object self, String operation, boolean responseExpected) throws LocationForward, FailureException {
while (true) {
org.apache.yoko.orb.OB.Downcall downcall = createDowncall(
operation, responseExpected);
try {
org.apache.yoko.orb.CORBA.OutputStream out = preMarshal(downcall);
//
// The InvocationContext is associated with the OutputStream
// and retrieved by invoke()
//
InvocationContext ctx = new InvocationContext();
ctx.downcallStub = this;
ctx.downcall = downcall;
out._OB_invocationContext(ctx);
out._OB_ORBInstance(this._OB_getORBInstance());
return out;
} catch (FailureException ex) {
handleFailureException(downcall, ex);
}
}
}
//
// Prepare a polling request from a portable stub
//
// public org.apache.yoko.orb.CORBA.OutputStream
public org.apache.yoko.orb.OB.CodeConverters setupPollingRequest(
ServiceContextListHolder sclHolder, org.apache.yoko.orb.CORBA.OutputStreamHolder out)
throws FailureException {
//
// Create buffer to contain out marshalable data
//
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
//
// Obtain information regarding our target
//
org.apache.yoko.orb.OCI.ProfileInfoHolder info = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
Client client = getClientProfilePair(info);
out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client.codeConverters(), GIOP1_2);
sclHolder.value = client.getAMIRouterSCL();
//
// Be sure to add the invocation context before returning
//
InvocationContext ctx = new InvocationContext();
ctx.downcallStub = this;
ctx.downcall = null;
out.value._OB_invocationContext(ctx);
return client.codeConverters();
}
//
// Creates an output stream that holds an AMI router request. Note
// that this needs to be done in two parts. The first (this method)
// creates the initial stream and writes the request header. The
// second will complete the request by writing the message header into
// the stream (this needs to be done after we write the requests
// parameters)
//
public GIOPOutgoingMessage AMIRouterPreMarshal(String operation,
boolean responseExpected,
org.apache.yoko.orb.CORBA.OutputStreamHolder out,
org.apache.yoko.orb.OCI.ProfileInfoHolder info)
throws FailureException {
//
// Create buffer to contain our marshalable data
//
org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
12);
buf.pos(12);
//
// Obtain information regarding our target
//
Client client = getClientProfilePair(info);
out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client.codeConverters(), GIOP1_2);
ServiceContext[] scl = client.getAMIRouterSCL();
GIOPOutgoingMessage outgoing = new GIOPOutgoingMessage(orbInstance_, out.value, info.value);
//
// Put the request header into the stream
//
outgoing.writeRequestHeader(client.requestId(), operation, responseExpected, scl);
return outgoing;
}
public void AMIRouterPostMarshal(GIOPOutgoingMessage outgoing, org.apache.yoko.orb.CORBA.OutputStreamHolder out) {
int pos = out.value._OB_pos();
out.value._OB_pos(0);
outgoing.writeMessageHeader(MsgType_1_1.Request, false, pos - 12);
out.value._OB_pos(pos);
//
// The InvocationContext is associated with the OutputStream
// and retrieved by ami_*_request
//
InvocationContext ctx = new InvocationContext();
ctx.downcallStub = this;
ctx.downcall = null; // no downcall associated with an AMI request
out.value._OB_invocationContext(ctx);
}
//
// Invoke a request from a portable stub
//
public org.apache.yoko.orb.CORBA.InputStream invoke(
org.omg.CORBA.Object self,
org.apache.yoko.orb.CORBA.OutputStream out)
throws ApplicationException,
RemarshalException, LocationForward,
FailureException {
//
// We should have an InvocationContext associated with the
// OutputStream
//
org.apache.yoko.orb.CORBA.OutputStream o = out;
InvocationContext ctx = (InvocationContext) o._OB_invocationContext();
Assert._OB_assert(ctx != null);
//
// If the DowncallStub has changed, then remarshal
//
if (ctx.downcallStub != this) {
throw new RemarshalException();
}
Downcall down = ctx.downcall;
//
// No while loop here - if we need to reinvoke, we must raise
// RemarshalException
//
try {
down.postMarshal();
boolean response = down.responseExpected();
if (response) {
down.request();
}
else {
down.oneway();
}
if (response) {
org.apache.yoko.orb.CORBA.InputStream in = down.preUnmarshal();
if (down.userException()) {
String id = null;
try {
//
// Extract the exception's repository ID
//
id = down.unmarshalExceptionId();
} catch (SystemException ex) {
down.unmarshalEx(ex);
}
//
// We're using portable stubs, so we'll never
// be given the user exception instance. Therefore,
// we might as well invoke the interceptors now.
//
down.setUserException(id);
down.postUnmarshal();
throw new ApplicationException(id, in);
} else {
//
// We're using portable stubs, so we'll never
// know the unmarshalled results. Therefore,
// we might as well invoke the interceptors now.
//
down.postUnmarshal();
return in;
}
} else {
down.preUnmarshal();
down.postUnmarshal();
return null;
}
} catch (FailureException ex) {
handleFailureException(down, ex);
}
//
// If we reach this point, then we need to reinvoke
//
throw new RemarshalException();
}
public org.omg.CORBA.Object getAMIPollTarget() {
//
// Since we don't have access to the IOR information in the
// generated stub, we will call this method to create the target
// object for a polling request
//
org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
return objectFactory.createObject(IOR_);
}
public PersistentRequest ami_poll_request(OutputStream out, String operation, ServiceContext[] scl) throws RemarshalException {
//
// setup the ORBInstance
//
// poller._OB_ORBInstance(orbInstance_);
Assert._OB_assert(out != null);
//
// We should have an InvocationContext associated with the OutputStream
//
org.apache.yoko.orb.CORBA.OutputStream o = (org.apache.yoko.orb.CORBA.OutputStream) out;
InvocationContext ctx = (InvocationContext) o._OB_invocationContext();
Assert._OB_assert(ctx != null);
//
// If the DowncallStub has changed, then remarshal
//
if (ctx.downcallStub != this)
throw new RemarshalException();
//
// Obtain the ORB
//
ORB orb = orbInstance_.getORB();
Assert._OB_assert(orb != null);
//
// Obtain the PersistentRequestRouter
//
PersistentRequestRouter router = org.apache.yoko.orb.OB.MessageRoutingUtil.getPersistentRouterFromConfig(orbInstance_);
org.apache.yoko.orb.OB.Assert._OB_assert(router != null);
//
// Obtain information regarding our target
//
org.apache.yoko.orb.OCI.ProfileInfoHolder info = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
info.value = null;
try {
getClientProfilePair(info);
} catch (org.apache.yoko.orb.OB.FailureException ex) {
throw new RemarshalException();
}
//
// Get the profile index
//
short index = (short) info.value.index;
//
// Create the router to_visit list
//
RouterListHolder to_visit = new RouterListHolder();
to_visit.value = new Router[0];
org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(orbInstance_, info.value, to_visit);
//
// Obtain the target objects
//
org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
org.omg.CORBA.Object target = objectFactory.createObject(IOR_);
//
// Populate the RequestMessage payload
//
RequestMessage payload = new RequestMessage();
// payload.service_contexts = new ServiceContext[0];
//
// XXX
//
payload.service_contexts = scl;
payload.giop_version = new org.omg.GIOP.Version();
payload.giop_version.major = info.value.major;
payload.giop_version.minor = info.value.minor;
payload.response_flags = 1;
payload.reserved = new byte[3];
payload.reserved[0] = 0;
payload.reserved[1] = 0;
payload.reserved[2] = 0;
payload.operation = operation;
payload.object_key = new byte[info.value.key.length];
System.arraycopy(info.value.key, 0, payload.object_key, 0, info.value.key.length);
o._OB_pos(0);
org.apache.yoko.orb.OCI.Buffer buf = o._OB_buffer();
MessageBody messageBody = new MessageBody();
messageBody.byte_order = false; // Java is always false
messageBody.body = new byte[buf.rest_length()];
System.arraycopy(buf.data(), buf.pos(), messageBody.body, 0, buf.rest_length());
payload.body = messageBody;
//
// Empty QoS list
//
Policy[] qosList = new Policy[0];
//
// Create a new Persistent request
//
PersistentRequest request = router.create_persistent_request(index, to_visit.value, target, qosList, payload);
//
// Return the persistent request back to the stub
//
return request;
}
public boolean ami_callback_request(OutputStream out, ReplyHandler reply, org.apache.yoko.orb.OCI.ProfileInfo info) throws RemarshalException {
//
// We should have an InvocationContext associated with the
// OutputStream
//
org.apache.yoko.orb.CORBA.OutputStream o = (org.apache.yoko.orb.CORBA.OutputStream) out;
InvocationContext ctx = (InvocationContext) o._OB_invocationContext();
Assert._OB_assert(ctx != null);
//
// If the DowncallStub has changed, then remarshal
//
if (ctx.downcallStub != this)
throw new RemarshalException();
org.apache.yoko.orb.CORBA.InputStream tmpIn = (org.apache.yoko.orb.CORBA.InputStream) out.create_input_stream();
//
// Unmarshal the message header
//
MessageHeader_1_1 msgHeader = MessageHeader_1_2Helper.read(tmpIn);
//
// Check the GIOP version
//
if (!(msgHeader.GIOP_version.major >= 1 && msgHeader.GIOP_version.minor >= 2)) {
//
// Report error - throw exception?
//
return false;
}
//
// Check the message type
//
if (msgHeader.message_type != (byte) MsgType_1_1._Request) {
//
// Report error - throw exception
//
return false;
}
//
// Create and populate a RequestInfo to send to the router
//
RequestInfo requestInfo = new RequestInfo();
//
// Unmarshal the request header
//
RequestHeader_1_2 requestHeader = RequestHeader_1_2Helper.read(tmpIn);
//
// Create and populate a RequestInfo structure to send to the
// Router
//
RouterListHolder configRouterList = new RouterListHolder();
configRouterList.value = new Router[0];
//
// Populate the configRouterList
//
org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(orbInstance_, info, configRouterList);
requestInfo.visited = new Router[0];
requestInfo.to_visit = new Router[0];
//
// Get the target for this request
//
org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
//
// REVISIT: Should we be using IOR_ or origIOR_?
//
requestInfo.target = objectFactory.createObject(IOR_);
//
// Get the index of the profile being used
//
requestInfo.profile_index = (short) info.index;
//
// Get the reply destination for this request
//
ReplyDestination replyDest = new ReplyDestination();
replyDest.handler_type = ReplyDisposition.TYPED;
replyDest.handler = reply;
requestInfo.reply_destination = replyDest;
//
// Get the selected qos for this request
//
PolicyValueSeqHolder invocPoliciesHolder = new PolicyValueSeqHolder();
invocPoliciesHolder.value = new PolicyValue[0];
org.apache.yoko.orb.OB.MessageRoutingUtil.getInvocationPolicyValues(policies_, invocPoliciesHolder);
requestInfo.selected_qos = invocPoliciesHolder.value;
//
// Create payload (RequestMessage) for this request
//
RequestMessage requestMessage = new RequestMessage();
requestMessage.giop_version = new org.omg.GIOP.Version();
requestMessage.giop_version.major = info.major;
requestMessage.giop_version.minor = info.minor;
//
// Get the service contexts for this request
//
requestMessage.service_contexts = requestHeader.service_context;
//
// Add the invocation policies service context for this request.
// Note that this can change from request to request
//
ServiceContext invocPoliciesSC = new ServiceContext();
invocPoliciesSC.context_id = INVOCATION_POLICIES.value;
//
// Create an output stream an write the PolicyValueSeq
//
if (invocPoliciesHolder.value != null) {
org.apache.yoko.orb.OCI.Buffer scBuf = new org.apache.yoko.orb.OCI.Buffer();
org.apache.yoko.orb.CORBA.OutputStream scOut = new org.apache.yoko.orb.CORBA.OutputStream(
scBuf);
scOut._OB_writeEndian();
PolicyValueSeqHelper.write(scOut, invocPoliciesHolder.value);
invocPoliciesSC.context_data = new byte[scOut._OB_pos()];
System.arraycopy(invocPoliciesSC.context_data, 0, scBuf.data(), 0, scBuf.length());
}
//
// Add the service context to the list of current service contexts
//
int scLength = requestMessage.service_contexts.length;
ServiceContext[] scList = new ServiceContext[scLength + 1];
System.arraycopy(requestMessage.service_contexts, 0, scList, 0, scLength);
scList[scLength] = invocPoliciesSC;
//
// Get the response flags for the request
//
requestMessage.response_flags = requestHeader.response_flags;
//
// Reserved octets
//
requestMessage.reserved = new byte[3];
requestMessage.reserved[0] = requestHeader.reserved[0];
requestMessage.reserved[1] = requestHeader.reserved[1];
requestMessage.reserved[2] = requestHeader.reserved[2];
//
// Get the object key for the request
//
int keyLen = info.key.length;
requestMessage.object_key = new byte[keyLen];
System.arraycopy(info.key, 0, requestMessage.object_key, 0, keyLen);
//
// Get the operation name for the request
//
requestMessage.operation = requestHeader.operation;
//
// Get the body of the request message
//
MessageBody messageBody = new MessageBody();
//
// Java is always big endian
//
messageBody.byte_order = false;
org.apache.yoko.orb.OCI.Buffer buf = tmpIn._OB_buffer();
//
// Align to an 8 byte boundary if we have something left
//
if (buf.rest_length() > 0) {
buf.pos((buf.pos() + 7) & ~7);
}
//
// Copy in the rest of the message body
//
messageBody.body = new byte[buf.rest_length()];
System.arraycopy(buf.data_, buf.pos(), messageBody.body, 0, buf.rest_length());
requestMessage.body = messageBody;
//
// Add the payload to the RequestInfo
//
requestInfo.payload = requestMessage;
//
// Now we have to try send the request to a router
//
boolean delivered = false;
int numRouters = configRouterList.value.length;
for (int i = numRouters - 1; (delivered == false) && (i >= 0); --i) {
Router curRouter = configRouterList.value[i];
//
// We only add the routers that we have attempted to contact to
// the to_visit list. This ensures that if a router accepts
// the request, then the lower priority routers are not added
//
int curLength = requestInfo.to_visit.length;
Router[] toVisit = new Router[curLength + 1];
if (curLength > 0) {
System.arraycopy(requestInfo.to_visit, 0, toVisit, 1, curLength);
}
toVisit[0] = curRouter;
requestInfo.to_visit = toVisit;
try {
curRouter.send_request(requestInfo);
//
// Success: stop processing
//
delivered = true;
} catch (SystemException ex) {
logger.log(Level.FINE, "Failed to contact router: " + ex.getMessage(), ex);
//
// Failure: try the next router in the list
//
}
}
//
// return whether we were successful or not
//
return delivered;
}
public void _OB_closeConnection(boolean terminate) {
destroy(terminate);
}
//
// Need to be able to access the ORB instance from a stub for AMI
// polling
//
public ORBInstance _OB_getORBInstance() {
return orbInstance_;
}
}