/*
* 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.
*
*/
package org.jacorb.orb.portableInterceptor;
import java.util.Collection;
import java.util.Map;
import org.jacorb.orb.ApplicationExceptionHelper;
import org.jacorb.orb.Delegate;
import org.jacorb.orb.Delegate.INVOCATION_KEY;
import org.jacorb.orb.SystemExceptionHelper;
import org.jacorb.orb.giop.ReplyInputStream;
import org.omg.CORBA.portable.ApplicationException;
import org.omg.CORBA.portable.RemarshalException;
import org.omg.GIOP.ReplyHeader_1_2;
import org.omg.GIOP.ReplyStatusType_1_2;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.ForwardRequest;
import org.omg.PortableInterceptor.LOCATION_FORWARD;
import org.omg.PortableInterceptor.SUCCESSFUL;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.omg.PortableInterceptor.USER_EXCEPTION;
import org.omg.TimeBase.UtcT;
import org.slf4j.Logger;
/**
* An instance of this class handles all interactions between one particular
* client request and any interceptors registered for it.
*
* @author Andre Spiegel
*/
public class DefaultClientInterceptorHandler implements ClientInterceptorHandler
{
private final ClientRequestInfoImpl info;
private final Logger logger;
private boolean isLocal = false;
/**
* Constructs an interceptor handler for the given parameters.
* If no interceptors are registered on the client side,
* the resulting object will be a dummy object that does nothing when
* invoked.
*
* @param original a <code>ClientInterceptorHandler</code> value which contains
* the original info and hence the original forward_request. May be null.
* @param orb an <code>org.jacorb.orb.ORB</code> value
* @param ros an <code>org.jacorb.orb.giop.RequestOutputStream</code> value
* @param self an <code>org.omg.CORBA.Object</code> value
* @param delegate an <code>org.jacorb.orb.Delegate</code> value
* @param piorOriginal an <code>org.jacorb.orb.ParsedIOR</code> value
* @param connection an <code>org.jacorb.orb.giop.ClientConnection</code> value
*/
public DefaultClientInterceptorHandler
( DefaultClientInterceptorHandler original,
org.jacorb.orb.ORB orb,
org.jacorb.orb.giop.RequestOutputStream ros,
org.omg.CORBA.Object self,
org.jacorb.orb.Delegate delegate,
org.jacorb.orb.ParsedIOR piorOriginal,
org.jacorb.orb.giop.ClientConnection connection )
{
if ( orb.hasClientRequestInterceptors() )
{
info = new ClientRequestInfoImpl (
orb,
(original != null ? original.info : null), // The original ClientInterceptorHandler might be null
ros,
self,
delegate,
piorOriginal,
connection,
Delegate.getInvocationContext().peek());
}
else
{
info = null;
}
logger =
orb.getConfiguration().getLogger("org.jacorb.orb.client_interceptors");
}
/**
* Constructor to be used for calls involving local objects that have interceptors,
* these calls will not have input or output streams, or requests
*/
public DefaultClientInterceptorHandler (org.jacorb.orb.ORB orb,
String operation,
boolean response_expected,
short sync_scope,
org.omg.CORBA.Object self,
org.jacorb.orb.Delegate delegate,
org.jacorb.orb.ParsedIOR piorOriginal)
{
info = new ClientRequestInfoImpl (orb,
operation,
response_expected,
sync_scope,
self,
delegate,
piorOriginal,
(Map<INVOCATION_KEY, UtcT>) Delegate.getInvocationContext().peek());
isLocal = true;
logger =
orb.getConfiguration().getLogger("org.jacorb.orb.client_interceptors");
}
public void handle_send_request()
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
invokeInterceptors ( info, ClientInterceptorIterator.SEND_REQUEST );
/**
* If it's local then there is no request output stream so we
* can't do this here
*/
if ( !(isLocal) )
{
// Add any new service contexts to the message
Collection<ServiceContext> ctx = info.getRequestServiceContexts ();
for (ServiceContext s : ctx)
{
info.request_os.addServiceContext (s);
}
}
}
}
public void handle_location_forward ( ReplyInputStream reply,
org.omg.CORBA.Object forward_reference )
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
info.setReplyStatus (LOCATION_FORWARD.value);
info.setForwardReference (forward_reference);
if (reply != null)
{
//allow interceptors access to reply input stream
info.reply_is = reply;
info.setReplyServiceContexts( reply.rep_hdr.service_context );
}
invokeInterceptors( info,
ClientInterceptorIterator.RECEIVE_OTHER );
}
}
public void handle_receive_reply ( ReplyInputStream reply )
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
if (reply != null)
{
ReplyHeader_1_2 header = reply.rep_hdr;
if ( header.reply_status.value() == ReplyStatusType_1_2._NO_EXCEPTION )
{
info.setReplyStatus (SUCCESSFUL.value);
info.setReplyServiceContexts( header.service_context );
// the case that invoke was called from
// dii.Request._invoke() will be handled inside
// of dii.Request._invoke() itself, because the
// result will first be available there
if ( info.request_os.getRequest() == null )
{
InterceptorManager manager = info.orb.getInterceptorManager();
info.setCurrent (manager.getCurrent());
//allow interceptors access to reply input stream
info.reply_is = reply;
invokeInterceptors( info,
ClientInterceptorIterator.RECEIVE_REPLY );
}
else
{
info.request_os.getRequest().setInfo( info );
}
}
}
else
{
info.setReplyStatus (SUCCESSFUL.value);
invokeInterceptors( info,
ClientInterceptorIterator.RECEIVE_REPLY );
}
}
}
public void handle_receive_other ( short reply_status )
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
info.setReplyStatus (reply_status);
invokeInterceptors ( info, ClientInterceptorIterator.RECEIVE_OTHER );
}
}
public void handle_receive_exception ( org.omg.CORBA.SystemException exception )
throws RemarshalException, ForwardRequest
{
handle_receive_exception ( exception, null );
}
public void handle_receive_exception ( org.omg.CORBA.SystemException exception,
ReplyInputStream reply )
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
SystemExceptionHelper.insert ( info.received_exception, exception );
try
{
info.received_exception_id =
SystemExceptionHelper.type ( exception ).id();
}
catch ( org.omg.CORBA.TypeCodePackage.BadKind bk )
{
if (logger.isDebugEnabled())
{
logger.debug("BadKind: " + bk.getMessage());
}
}
info.setReplyStatus (SYSTEM_EXCEPTION.value);
if ( reply != null )
{
info.setReplyServiceContexts ( reply.rep_hdr.service_context );
info.reply_is = reply;
}
invokeInterceptors ( info,
ClientInterceptorIterator.RECEIVE_EXCEPTION );
}
}
public void handle_receive_exception ( ApplicationException exception,
ReplyInputStream reply )
throws RemarshalException, ForwardRequest
{
if ( info != null )
{
info.received_exception_id = exception.getId();
try
{
ApplicationExceptionHelper.insert( info.received_exception,
exception );
}
catch ( Exception e )
{
if (logger.isDebugEnabled())
{
logger.debug(e.getMessage());
}
SystemExceptionHelper.insert ( info.received_exception,
new org.omg.CORBA.UNKNOWN
( e.getMessage() ) );
}
info.setReplyStatus (USER_EXCEPTION.value);
if (reply != null)
{
try
{
reply.reset();
}
catch ( Exception e )
{
// shouldn't happen anyway
logger.warn("unexpected exception", e);
}
info.setReplyServiceContexts ( reply.rep_hdr.service_context );
info.reply_is = reply;
}
invokeInterceptors ( info,
ClientInterceptorIterator.RECEIVE_EXCEPTION );
}
}
/**
* Where it is a local call there are not streams/requests so we need to get
* data directly from the info.
*/
public ClientRequestInfoImpl getInfo()
{
return info;
}
private void invokeInterceptors( ClientRequestInfoImpl info, short op )
throws RemarshalException, ForwardRequest
{
final ClientInterceptorIterator intercept_iter =
info.orb.getInterceptorManager().getClientIterator();
try
{
intercept_iter.iterate( info, op );
}
catch ( org.omg.PortableInterceptor.ForwardRequest fwd )
{
// This allows SendRequest to access the forwarded object.
//
// Note that the current version of the specification does not
// permit forward_reference to be accessed by SendRequest; this
// modification is a PrismTech enhancement complying to one of the
// suggested portable solutions within
// http://www.omg.org/issues/issue5266.txt.
info.setForwardReference(fwd.forward);
/**
* If its a local call there is no reply so we simply rethrow
* the ForwardRequest
*/
if (isLocal)
{
throw fwd;
}
else
{
info.delegate.forwardToObj (fwd.forward );
throw new RemarshalException();
}
}
catch ( org.omg.CORBA.UserException ue )
{
if (logger.isWarnEnabled())
{
logger.warn("UserException: " + ue.toString());
}
}
}
}