package org.jacorb.orb.portableInterceptor;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1999-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.util.ArrayList;
import java.util.Collection;
import org.jacorb.orb.dsi.ServerRequest;
import org.jacorb.orb.giop.GIOPConnection;
import org.jacorb.orb.giop.ReplyOutputStream;
import org.jacorb.orb.giop.RequestInputStream;
import org.jacorb.poa.POA;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.INV_POLICY;
import org.omg.CORBA.NO_RESOURCES;
import org.omg.CORBA.Policy;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.UserException;
import org.omg.Dynamic.Parameter;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.InvalidSlot;
import org.omg.PortableInterceptor.LOCATION_FORWARD;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.omg.PortableInterceptor.ServerRequestInfo;
import org.omg.PortableInterceptor.UNKNOWN;
import org.omg.PortableInterceptor.USER_EXCEPTION;
import org.omg.PortableServer.Servant;
/**
* This class represents the type of info object
* that will be passed to the ServerRequestInterceptors. <br>
* See PI Spec p.5-50ff
*
* @author Nicolas Noffke
*/
public class ServerRequestInfoImpl
extends RequestInfoImpl
implements ServerRequestInfo
{
private static final long serialVersionUID = -9044446354286649195L;
//from ServerRequestInfo
private byte[] adapter_id = null;
private String [] adapter_name = null;
private String target_most_derived_interface = null;
private Servant servant = null;
private final String operation;
private final boolean response_expected;
private final int requestId;
private final byte [] objectId;
private final ServerRequest request;
protected Any sending_exception = null;
public ServerRequestInfoImpl( org.jacorb.orb.ORB orb,
ServerRequest request,
Servant servant)
{
super(orb);
this.request = request;
operation = request.operation();
response_expected = request.responseExpected();
sync_scope = request.syncScope();
requestId = request.requestId();
objectId = request.objectId();
if (servant != null)
{
setServant(servant);
}
setRequestServiceContexts(request.getServiceContext());
sending_exception = orb.create_any();
}
/**
* This constructor is to cater for local calls where portable
* interceptors are involved. These calls are now handled
* locally rather than via the remote request mechanism so there
* will be no request from which to obtain information
*
* @param orb the orb
* @param contexts the contexts
* @param servant the servant
* @param objectId the object id
* @param operation the operation
* @param response_expected the response_expected
* @param sync_scope the sync_scope
*/
public ServerRequestInfoImpl( org.jacorb.orb.ORB orb,
Collection<ServiceContext> contexts,
Servant servant,
byte[] objectId,
String operation,
boolean response_expected,
short sync_scope)
{
super(orb);
this.operation = operation;
this.response_expected = response_expected;
this.sync_scope = sync_scope;
this.objectId = objectId;
requestId = 0;
request = null;
if (servant != null)
{
setServant(servant);
}
if (contexts != null)
{
setRequestServiceContexts(contexts.toArray (new ServiceContext[contexts.size ()]));
}
sending_exception = orb.create_any();
}
/**
* The servant is sometimes not available on calling
* receive_request_service_contexts (e.g. in case of
* ServantLocators or ServantActivators).
*/
public final void setServant(Servant servant)
{
this.servant = servant;
org.jacorb.poa.POA poa = (org.jacorb.poa.POA) servant._poa();
adapter_id = poa.getPOAId();
String[] all_ifs = servant._all_interfaces(poa, servant._object_id());
target_most_derived_interface = all_ifs[0];
POA parent = poa;
ArrayList<String> al = new ArrayList<String> ();
while (parent != null)
{
al.add (parent.the_name ());
parent = (POA) parent.the_parent ();
}
int size = al.size ();
adapter_name = new String [size];
// We can't just do toArray as otherwise adapter_name would be in
// reverse order.
for (int j = 0, i = (size-1); i >= 0; i--, j++)
{
adapter_name [j] = al.get (i);
}
}
/**
* Set the sending_exception attribute.
*/
public void update()
{
if (request != null)
{
if (! request.streamBased())
{
Any user_ex = request.except();
if (user_ex != null)
{
sending_exception = user_ex;
}
}
SystemException sys_ex = request.getSystemException();
if (sys_ex != null)
{
org.jacorb.orb.SystemExceptionHelper.insert(sending_exception, sys_ex);
}
forward_reference = request.getForwardReference();
}
}
/**
* Method introduced for local invocations as there is no Reply or Stream
* involved
*/
public void updateException (Throwable ex)
{
if (ex instanceof org.omg.CORBA.SystemException)
{
org.jacorb.orb.SystemExceptionHelper.insert (sending_exception,
( org.omg.CORBA.SystemException) ex);
setReplyStatus (SYSTEM_EXCEPTION.value);
}
else if (ex instanceof org.omg.PortableInterceptor.ForwardRequest)
{
forward_reference = (( org.omg.PortableInterceptor.ForwardRequest) ex).forward;
setReplyStatus (LOCATION_FORWARD.value);
}
else if (ex instanceof UserException)
{
org.jacorb.orb.SystemExceptionHelper.insert
(
sending_exception,
new org.omg.CORBA.UNKNOWN ("Received UserException " + ex)
);
setReplyStatus (USER_EXCEPTION.value);
}
}
/**
* returns a reference to the calls target.
*/
public org.omg.CORBA.Object target()
{
return servant._this_object();
}
// implementation of RequestInfoOperations interface
@Override
public Parameter[] arguments()
{
if (!(caller_op == ServerInterceptorIterator.RECEIVE_REQUEST) &&
!(caller_op == ServerInterceptorIterator.SEND_REPLY))
{
throw new BAD_INV_ORDER("The attribute \"arguments\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
if (arguments == null)
{
throw new NO_RESOURCES("Stream-based skeletons/stubs do not support this op",
1, CompletionStatus.COMPLETED_MAYBE);
}
return arguments;
}
@Override
public TypeCode[] exceptions()
{
throw new NO_RESOURCES("This feature is not supported on the server side",
1, CompletionStatus.COMPLETED_MAYBE);
}
@Override
public Any result()
{
if ( caller_op != ServerInterceptorIterator.SEND_REPLY )
{
throw new BAD_INV_ORDER("The attribute \"result\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
Any result = null;
try
{
if (request != null)
{
result = request.result();
}
}
catch(Exception e)
{
}
if (result == null)
{
throw new NO_RESOURCES("Stream-based skeletons/stubs do not support this op",
1, CompletionStatus.COMPLETED_MAYBE);
}
return result;
}
@Override
public short sync_scope()
{
return sync_scope;
}
@Override
public short reply_status()
{
if ((caller_op == ServerInterceptorIterator.RECEIVE_REQUEST ||
caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS) &&
reply_status != UNKNOWN.value)
{
throw new BAD_INV_ORDER("The attribute \"reply_status\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
return reply_status;
}
@Override
public org.omg.CORBA.Object forward_reference()
{
if (! (caller_op != ServerInterceptorIterator.SEND_OTHER) ||
(reply_status != LOCATION_FORWARD.value))
{
throw new BAD_INV_ORDER("The attribute \"forward_reference\" is currently " +
"invalid!", 10, CompletionStatus.COMPLETED_MAYBE);
}
return forward_reference;
}
@Override
public ServiceContext get_reply_service_context(int id)
{
if ((caller_op == ServerInterceptorIterator.RECEIVE_REQUEST) ||
(caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS))
{
throw new BAD_INV_ORDER("The operation \"get_reply_service_context\" is " +
"currently invalid!", 10,
CompletionStatus.COMPLETED_MAYBE);
}
return super.get_reply_service_context(id);
}
@Override
public String operation()
{
return operation;
}
@Override
public int request_id()
{
return requestId;
}
@Override
public boolean response_expected()
{
return response_expected;
}
// implementation of ServerRequestInfoOperations interface
@Override
public Any sending_exception()
{
if (caller_op != ServerInterceptorIterator.SEND_EXCEPTION)
{
throw new BAD_INV_ORDER("The attribute \"sending_exception\" is " +
"currently invalid!", 10,
CompletionStatus.COMPLETED_MAYBE);
}
return sending_exception;
}
@Override
public byte[] object_id()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER("The attribute \"object_id\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
return objectId;
}
@Override
public byte[] adapter_id()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER("The attribute \"adapter_id\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
return adapter_id;
}
@Override
public String orb_id()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER ("The attribute \"orb_id\" is currently invalid!",
14,
CompletionStatus.COMPLETED_MAYBE);
}
return orb.id();
}
@Override
public String server_id()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new NO_RESOURCES ("The attribute \"server_id\" is not available",
1,
CompletionStatus.COMPLETED_MAYBE);
}
else
{
throw new BAD_INV_ORDER ("The attribute \"server_id\" is currently invalid!",
14,
CompletionStatus.COMPLETED_MAYBE);
}
}
@Override
public String [] adapter_name()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER ("The attribute \"adapter_name\" is currently invalid!",
14,
CompletionStatus.COMPLETED_MAYBE);
}
return adapter_name;
}
@Override
public String target_most_derived_interface()
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER("The attribute \"target_most_derived_interface\" is " +
"currently invalid!", 10,
CompletionStatus.COMPLETED_MAYBE);
}
return target_most_derived_interface;
}
/**
* WARNING: This method relies on the DomainService to be available.
* Make shure that the DS is running, if you want to call this method.
*/
@Override
public Policy get_server_policy(int type) {
if (! orb.hasPolicyFactoryForType(type))
{
throw new INV_POLICY("No PolicyFactory for type " + type +
" has been registered!", 2,
CompletionStatus.COMPLETED_MAYBE);
}
try
{
org.jacorb.orb.ServantDelegate delegate = (org.jacorb.orb.ServantDelegate) servant._get_delegate();
return delegate._get_policy(servant._this_object(), type);
}
catch(INV_POLICY e)
{
e.minor = 2;
throw e;
}
}
@Override
public void set_slot(int id, Any data) throws InvalidSlot
{
current.set_slot(id, data);
}
@Override
public boolean target_is_a(String id)
{
if (caller_op == ServerInterceptorIterator.RECEIVE_REQUEST_SERVICE_CONTEXTS)
{
throw new BAD_INV_ORDER("The operation \"target_is_a\" is currently invalid!",
10, CompletionStatus.COMPLETED_MAYBE);
}
return servant._is_a(id);
}
@Override
public void add_reply_service_context(ServiceContext service_context,
boolean replace)
{
Integer _id = Integer.valueOf (service_context.context_id);
if (! replace && reply_ctx.containsKey(_id))
{
throw new BAD_INV_ORDER("The ServiceContext with id " + _id.toString()
+ " has already been set!", 11,
CompletionStatus.COMPLETED_MAYBE);
}
reply_ctx.put(_id, service_context);
}
/**
* Public accessor to return the connection being used by this ServerRequestInfoImpl.
*
* @return the connection (maybe null if local call and no connection has been used).
*/
public GIOPConnection getConnection()
{
return (request == null ? null : request.getConnection());
}
/**
* Public accessor to determine if this interceptor is being used in a local call.
*
* @return true if this is a local interceptor.
*/
public boolean isLocalInterceptor()
{
return (getConnection() == null);
}
// These functions should NOT be used internally and are only provided
// to allow users to interrogate the streams.
/**
* Public accessor to access the internal reply stream. Using this API it
* may be possible to corrupt the inputstream and therebye the call
* chain. Use at your own risk.
*/
public ReplyOutputStream getReplyStream ()
{
return request.get_out();
}
/**
* Public accessor to access the internal request stream. Using this API it
* may be possible to corrupt the outputstream and therebye the call
* chain. Use at your own risk.
*/
public RequestInputStream getRequestStream ()
{
return request.get_in();
}
/** Set the sending_exception Any. Used by RequestProcessor. */
public void sending_exception(Any any)
{
sending_exception = any;
}
}