package org.jacorb.orb;
/*
* 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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.jacorb.config.Configurable;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
import org.jacorb.ir.RepositoryID;
import org.jacorb.orb.giop.ReplyInputStream;
import org.jacorb.util.ObjectUtil;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.NO_IMPLEMENT;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.UserException;
import org.omg.GIOP.ReplyStatusType_1_2;
import org.slf4j.Logger;
/**
* JacORB-specific implementation of
* <code>org.omg.Messaging.ExceptionHolder</code>. An instance of this
* type is used to pass an exception to a reply handler.
*
* @author Andre Spiegel {@literal <spiegel@gnu.org>}
*/
public class ExceptionHolderImpl
extends org.omg.Messaging.ExceptionHolder
implements Configurable
{
private Logger logger = null;
private final ORB orb;
/**
* No-arg constructor for demarshaling.
*/
public ExceptionHolderImpl(ORB orb)
{
super();
this.orb = orb;
try
{
configure (orb.getConfiguration ());
}
catch (ConfigurationException ex)
{
throw new INTERNAL ("Caught configuration exception." + ex);
}
}
/**
* Constructs an ExceptionHolderImpl object from an input stream.
* It is assumed that the reply status of this input stream is
* either USER_EXCEPTION or SYSTEM_EXCEPTION. If it has another
* status, a RuntimeException is thrown.
*/
public ExceptionHolderImpl(ORB orb, ReplyInputStream inputStream )
{
this(orb);
int status = inputStream.getStatus().value();
if ( status == ReplyStatusType_1_2._USER_EXCEPTION )
{
is_system_exception = false;
}
else if ( status == ReplyStatusType_1_2._SYSTEM_EXCEPTION )
{
is_system_exception = true;
}
else
{
throw new BAD_PARAM( "attempt to create ExceptionHolder " +
"for non-exception reply" );
}
byte_order = inputStream.getLittleEndian();
marshaled_exception = inputStream.getBody();
}
public ExceptionHolderImpl(ORB orb, org.omg.CORBA.SystemException exception)
{
this(orb);
is_system_exception = true;
byte_order = false;
final CDROutputStream out = new CDROutputStream(orb);
try
{
SystemExceptionHelper.write(out, exception);
marshaled_exception = out.getBufferCopy();
}
finally
{
out.close();
}
}
@Override
public void configure(Configuration configuration)
throws ConfigurationException
{
logger =
configuration.getLogger("org.jacorb.orb.exc_holder");
}
@Override
public void raise_exception_with_list (TypeCode[] exc_list) throws UserException
{
throw new NO_IMPLEMENT ("NYI");
}
@Override
public void raise_exception()
throws UserException
{
final CDRInputStream input =
new CDRInputStream (orb, marshaled_exception, byte_order);
try
{
if ( is_system_exception )
{
throw SystemExceptionHelper.read( input );
}
input.mark( 0 );
String id = input.read_string();
try
{
input.reset();
}
catch( IOException e )
{
logger.error( "Unexpected IOException: ", e);
throw new INTERNAL("Unexpected IOException: " + e);
}
final UserException result;
try
{
result = exceptionFromHelper( id, input );
}
catch( Exception e )
{
logger.error("error reading exception", e);
throw new org.omg.CORBA.UnknownUserException();
}
throw result;
}
finally
{
input.close();
}
}
public void raise_exception_with_list( ExceptionList exc_list )
throws UserException
{
throw new org.omg.CORBA.NO_IMPLEMENT(
"raise_exception_with_list not yet implemented" );
}
/**
* For testing.
*/
@Override
public String toString()
{
StringBuffer result = new StringBuffer();
for (int i=0; i<marshaled_exception.length; i++)
{
result.append (marshaled_exception[i]);
result.append ('(');
result.append ((char)marshaled_exception[i]);
result.append (") ");
}
return result.toString();
}
/**
* Given a repository id, tries to find a helper for the corresponding
* class and uses it to unmarshal an instance of this class from
* the given InputStream.
*/
public org.omg.CORBA.UserException exceptionFromHelper
( String repositoryID,
org.omg.CORBA.portable.InputStream input )
throws ClassNotFoundException,
NoSuchMethodException,
IllegalAccessException,
InvocationTargetException
{
final String helperClassName = RepositoryID.className(repositoryID, "Helper", null);
try
{
final Class<?> helperClazz = ObjectUtil.classForName (helperClassName);
return exceptionFromHelper(input, helperClazz);
}
catch (ClassNotFoundException e)
{
final String repositoryIDWithoutPragmaPrefix = stripPragmaPrefix(repositoryID);
if ( ! repositoryIDWithoutPragmaPrefix.equals (repositoryID))
{
if (logger.isDebugEnabled())
{
logger.debug("unable to locate class " + helperClassName + " for repository ID " + repositoryID + ". Retrying without pragma prefix: " + repositoryIDWithoutPragmaPrefix);
}
return exceptionFromHelper(repositoryIDWithoutPragmaPrefix, input);
}
else
{
// if class doesn't exist, let exception propagate
throw e;
}
}
}
/**
* try to strip off pragma prefix information.
* returns the unmodified string if not possible
*/
private String stripPragmaPrefix(String original)
{
final int index = original.indexOf('.', 4);
final int versionIndex = original.lastIndexOf(':');
if (index > 0 && index < versionIndex)
{
return "IDL:" + original.substring(original.indexOf('/') + 1);
}
return original;
}
private org.omg.CORBA.UserException exceptionFromHelper(org.omg.CORBA.portable.InputStream input, Class<?> helperClazz) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException
{
// helper must not be null from here on
// get read method from helper and invoke it,
// i.e. read the object from the stream
final Method readMethod =
helperClazz.getMethod( "read", new Class[]{ org.omg.CORBA.portable.InputStream.class });
return ( org.omg.CORBA.UserException ) readMethod.invoke( null, new java.lang.Object[]{ input } );
}
/**
* Marshals this object into a new buffer and returns that buffer.
*/
public byte[] marshal()
{
final CDROutputStream out = new CDROutputStream( orb );
try
{
out.write_value( this, "IDL:omg.org/Messaging/ExceptionHolder:1.0" );
return out.getBufferCopy();
}
finally
{
out.close();
}
}
}