summaryrefslogtreecommitdiff
path: root/TAO/tao/Exception.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/Exception.cpp')
-rw-r--r--TAO/tao/Exception.cpp464
1 files changed, 464 insertions, 0 deletions
diff --git a/TAO/tao/Exception.cpp b/TAO/tao/Exception.cpp
new file mode 100644
index 00000000000..7c8e59d1da0
--- /dev/null
+++ b/TAO/tao/Exception.cpp
@@ -0,0 +1,464 @@
+// $id: Exception.cpp,v 1.29 1998/03/16 17:19:58 coryan Exp $
+
+// Copyright 1994-1995 by Sun Microsystems Inc.
+// All Rights Reserved
+//
+// ORB: Exception handling support
+//
+// THREADING NOTE: calling thread handles mutual exclusion policy
+// on all of these data structures.
+
+#include "tao/corba.h"
+
+// Static initializers.
+CORBA::TypeCode_ptr TAO_Exceptions::sys_exceptions[TAO_Exceptions::NUM_SYS_EXCEPTIONS];
+
+CORBA::ExceptionList TAO_Exceptions::system_exceptions;
+
+CORBA_Exception::CORBA_Exception (CORBA::TypeCode_ptr tc)
+ : type_ (tc),
+ refcount_ (0)
+{
+ if (type_)
+ type_->AddRef ();
+ assert (type_ != 0);
+}
+
+CORBA_Exception::CORBA_Exception (const CORBA_Exception &src)
+ : type_ (src.type_),
+ refcount_ (0)
+{
+ if (type_)
+ type_->AddRef ();
+ assert (type_ != 0);
+}
+
+// NOTE: It's this code, not anything defined in a subclass, which
+// is responsible for releasing any storage owned by the exception.
+// It can do this because it's got the typecode.
+
+CORBA_Exception::~CORBA_Exception (void)
+{
+ assert (refcount_ == 0);
+ assert (type_ != 0);
+
+ assert (1 == 2);
+}
+
+CORBA_Exception &
+CORBA_Exception::operator = (const CORBA_Exception &src)
+{
+ if (type_)
+ type_->Release ();
+ type_ = src.type_;
+ if (type_)
+ type_->AddRef ();
+ assert (type_ != 0);
+
+ return *this;
+}
+
+const char *
+CORBA_Exception::_id (void) const
+{
+ CORBA::Environment env;
+
+ if (type_)
+ return type_->id (env);
+ else
+ return 0;
+}
+
+TAO_CONST CORBA::TypeCode_ptr
+CORBA_Exception::_type (void) const
+{
+ return type_;
+}
+
+int
+CORBA_Exception::_is_a (const char* repository_id) const
+{
+ return (ACE_OS::strcmp (repository_id, "IDL:CORBA/Exception:1.0")==0);
+}
+
+CORBA::ULong
+CORBA_Exception::AddRef (void)
+{
+ return ++refcount_;
+}
+
+CORBA::ULong
+CORBA_Exception::Release (void)
+{
+ refcount_--;
+ if (refcount_ != 0)
+ return refcount_;
+
+ // CORBA::TypeCode_ptr tc = type_->_duplicate ();
+
+ CORBA::Any free_it_all (type_, this, CORBA::B_TRUE);
+
+ // tc->Release ();
+
+ return 0;
+}
+
+// Avoid zillions of not-quite-inlined copies of utilities.
+
+CORBA_UserException::CORBA_UserException (CORBA::TypeCode_ptr tc)
+ : CORBA_Exception (tc)
+{
+}
+
+CORBA_UserException::~CORBA_UserException (void)
+{
+}
+
+int
+CORBA_UserException::_is_a (const char* interface_id) const
+{
+ return ACE_OS::strcmp (interface_id,
+ "IDL:CORBA/UserException:1.0") == 0
+ || CORBA_Exception::_is_a (interface_id);
+}
+
+CORBA_UserException*
+CORBA_UserException::_narrow (CORBA_Exception* exception)
+{
+ if (exception->_is_a ("IDL:CORBA/UserException:1.0"))
+ return ACE_dynamic_cast (CORBA_UserException *, exception);
+ return 0;
+}
+
+CORBA_SystemException::CORBA_SystemException (CORBA::TypeCode_ptr tc,
+ CORBA::ULong code,
+ CORBA::CompletionStatus completed)
+ : CORBA_Exception (tc),
+ _minor (code),
+ _completed (completed)
+{
+}
+
+CORBA_SystemException::~CORBA_SystemException (void)
+{
+}
+
+int
+CORBA_SystemException::_is_a (const char* interface_id) const
+{
+ return ACE_OS::strcmp (interface_id,
+ "IDL:CORBA/SystemException:1.0") == 0
+ || CORBA_Exception::_is_a (interface_id);
+}
+
+CORBA_SystemException*
+CORBA_SystemException::_narrow (CORBA_Exception* exception)
+{
+ if (exception->_is_a ("IDL:CORBA/SystemException:1.0"))
+ return ACE_dynamic_cast (CORBA_SystemException*,exception);
+ return 0;
+}
+
+// Note that "buffer" holds the (unscoped) name originally, and is
+// then overwritten.
+
+void
+TAO_Exceptions::make_standard_typecode (CORBA::TypeCode_ptr tcp,
+ const char *name,
+ char *buffer,
+ size_t buflen,
+ CORBA::Environment &env)
+{
+ static const char *minor = "minor";
+ static const char *completion = "completion";
+
+ static const CORBA::ULong oc_completion_status [] =
+ {
+ TAO_ENCAP_BYTE_ORDER, // byte order flag, tricky
+ 0, 0, // type ID omitted
+ 3, // three members
+ 0, 0, // ... whose names are all omitted
+ 0, 0,
+ 0, 0
+ };
+ static CORBA::TypeCode
+ tc_completion_status (CORBA::tk_enum,
+ sizeof oc_completion_status,
+ (char *) &oc_completion_status,
+ CORBA::B_FALSE);
+
+ static const CORBA::TypeCode_ptr completion_status =
+ &tc_completion_status;
+
+ // Create a CDR stream ... juggle the alignment here a bit, we know
+ // it's good enough for the typecode.
+
+ CDR stream (buffer, buflen);
+
+ // into CDR stream, stuff (in order):
+ // - byte order flag [4 bytes]
+ // - exception ID [27 + N bytes]
+ // - exception name [4 + N bytes ]
+ // - number of members (2) [4 bytes ]
+ // - foreach member, { name string, typecode } [~40 bytes]
+
+ char full_id[100];
+ char *strptr = full_id;
+
+ (void) ACE_OS::sprintf (full_id,
+ "IDL:omg.org/CORBA/%s:1.0",
+ name);
+ // @@ Should this really be an assert or should we deal with it via
+ // exceptions?
+ assert (ACE_OS::strlen (full_id) <= sizeof full_id);
+
+ if (stream.put_byte (TAO_ENCAP_BYTE_ORDER) != CORBA::B_TRUE
+ || stream.encode (CORBA::_tc_string,
+ &strptr, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE
+ || stream.encode (CORBA::_tc_string,
+ &name, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE
+ || stream.put_ulong (2L) != CORBA::B_TRUE
+ || stream.encode (CORBA::_tc_string,
+ &minor, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE
+ || stream.encode (CORBA::_tc_TypeCode,
+ &CORBA::_tc_ulong, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE
+ || stream.encode (CORBA::_tc_string,
+ &completion, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE
+ || stream.encode (CORBA::_tc_TypeCode,
+ &completion_status, 0,
+ env) != CORBA::TypeCode::TRAVERSE_CONTINUE) {
+ env.exception (new CORBA_INITIALIZE (CORBA::COMPLETED_NO));
+ return;
+ }
+
+ // OK, we stuffed the buffer we were given (or grew a bigger one;
+ // hope to avoid that during initialization). Now build and return
+ // a TypeCode, saving it away in the list of ones that the ORB will
+ // always accept as part of any operation response!
+
+ sys_exceptions [TAO_Exceptions::system_exceptions.length++] =
+ new (tcp) CORBA::TypeCode (CORBA::tk_except,
+ stream.length (),
+ stream.buffer (),
+ CORBA::B_FALSE);
+
+ assert (tcp->length_ <= TAO_Exceptions::TC_BUFLEN);
+ return;
+}
+
+// List of standard/system exceptions ... used to create static
+// storage for their typecodes, then later to initialize that storage
+// using the routine above. (It's just too painful to init these
+// typecodes statically in all cases!)
+
+#define STANDARD_EXCEPTION_LIST \
+ TAO_SYSTEM_EXCEPTION (UNKNOWN) \
+ TAO_SYSTEM_EXCEPTION (BAD_PARAM) \
+ TAO_SYSTEM_EXCEPTION (NO_MEMORY) \
+ TAO_SYSTEM_EXCEPTION (IMP_LIMIT) \
+ TAO_SYSTEM_EXCEPTION (COMM_FAILURE) \
+ TAO_SYSTEM_EXCEPTION (INV_OBJREF) \
+ TAO_SYSTEM_EXCEPTION (OBJECT_NOT_EXIST) \
+ TAO_SYSTEM_EXCEPTION (NO_PERMISSION) \
+ TAO_SYSTEM_EXCEPTION (INTERNAL) \
+ TAO_SYSTEM_EXCEPTION (MARSHAL) \
+ TAO_SYSTEM_EXCEPTION (INITIALIZE) \
+ TAO_SYSTEM_EXCEPTION (NO_IMPLEMENT) \
+ TAO_SYSTEM_EXCEPTION (BAD_TYPECODE) \
+ TAO_SYSTEM_EXCEPTION (BAD_OPERATION) \
+ TAO_SYSTEM_EXCEPTION (NO_RESOURCES) \
+ TAO_SYSTEM_EXCEPTION (NO_RESPONSE) \
+ TAO_SYSTEM_EXCEPTION (PERSIST_STORE) \
+ TAO_SYSTEM_EXCEPTION (BAD_INV_ORDER) \
+ TAO_SYSTEM_EXCEPTION (TRANSIENT) \
+ TAO_SYSTEM_EXCEPTION (FREE_MEM) \
+ TAO_SYSTEM_EXCEPTION (INV_IDENT) \
+ TAO_SYSTEM_EXCEPTION (INV_FLAG) \
+ TAO_SYSTEM_EXCEPTION (INTF_REPOS) \
+ TAO_SYSTEM_EXCEPTION (BAD_CONTEXT) \
+ TAO_SYSTEM_EXCEPTION (OBJ_ADAPTER) \
+ TAO_SYSTEM_EXCEPTION (DATA_CONVERSION)
+
+// Declare static storage for these ... the buffer is "naturally"
+// aligned and overwritten.
+//
+// XXX this actually doesn't guarantee "natural" alignment, but
+// it works that way in most systems.
+
+#define TAO_SYSTEM_EXCEPTION(name) \
+ static CORBA::Long tc_buf_ ## name [TAO_Exceptions::TC_BUFLEN / sizeof (long)]; \
+ static CORBA::TypeCode tc_std_ ## name (CORBA::tk_except); \
+ CORBA::TypeCode_ptr CORBA::_tc_ ## name = &tc_std_ ## name;
+STANDARD_EXCEPTION_LIST
+#undef TAO_SYSTEM_EXCEPTION
+
+void
+TAO_Exceptions::init_standard_exceptions (CORBA::Environment &env)
+{
+ // Initialize the list of system exceptions, used when
+ // unmarshaling.
+ TAO_Exceptions::system_exceptions.length = 0;
+ TAO_Exceptions::system_exceptions.maximum =
+ TAO_Exceptions::NUM_SYS_EXCEPTIONS;
+ TAO_Exceptions::system_exceptions.buffer =
+ &TAO_Exceptions::sys_exceptions [0];
+
+ // Initialize the typecodes.
+#define TAO_SYSTEM_EXCEPTION(name) \
+ if (env.exception () == 0) \
+ TAO_Exceptions::make_standard_typecode (&tc_std_ ## name, #name, \
+ (char *) tc_buf_ ## name, \
+ sizeof tc_buf_ ## name, env);
+ STANDARD_EXCEPTION_LIST
+#undef TAO_SYSTEM_EXCEPTION
+ }
+
+#define TAO_SYSTEM_EXCEPTION(name) \
+int \
+CORBA_##name ::_is_a (const char* interface_id) const \
+{ \
+ return ((ACE_OS::strcmp (interface_id, "IDL:CORBA/" #name "1.0")==0) \
+ || CORBA_SystemException::_is_a (interface_id)); \
+}
+STANDARD_EXCEPTION_LIST
+#undef TAO_SYSTEM_EXCEPTION
+
+#define TAO_SYSTEM_EXCEPTION(name) \
+CORBA_##name * \
+CORBA_##name ::_narrow (CORBA_Exception* exception) \
+{ \
+ if (exception->_is_a ("IDL:CORBA/" #name "1.0")) \
+ return ACE_dynamic_cast (CORBA_##name *, exception); \
+ return 0; \
+}
+STANDARD_EXCEPTION_LIST
+#undef TAO_SYSTEM_EXCEPTION
+
+#undef STANDARD_EXCEPTION_LIST
+
+// Static initialization of the two user-defined exceptions that
+// are part of the ORB.
+
+static char tc_buf_Bounds [] =
+{
+ 0, 0, 0, 0, // big endian, padded
+ 0, 0, 0, 38, // strlen (id) + 1
+ 'I', 'D', 'L', ':',
+ 'o', 'm', 'g', '.',
+ 'o', 'r', 'g', '/',
+ 'C', 'O', 'R', 'B',
+ 'A', '/', 'T', 'y',
+ 'p', 'e', 'C', 'o',
+ 'd', 'e', '/', 'B',
+ 'o', 'u', 'n', 'd',
+ 's', ':', '1', '.',
+ '0', '\0', 0, 0,
+ 0, 0, 0, 0 // no members to this typecode
+};
+
+static CORBA::TypeCode tc_std_Bounds (CORBA::tk_except,
+ sizeof tc_buf_Bounds,
+ tc_buf_Bounds,
+ CORBA::B_FALSE);
+
+CORBA::TypeCode_ptr CORBA::_tc_Bounds = &tc_std_Bounds;
+
+static char tc_buf_BadKind [] =
+{
+ 0, 0, 0, 0, // big endian, padded
+ 0, 0, 0, 39, // strlen (id) + 1
+ 'I', 'D', 'L', ':',
+ 'o', 'm', 'g', '.',
+ 'o', 'r', 'g', '/',
+ 'C', 'O', 'R', 'B',
+ 'A', '/', 'T', 'y',
+ 'p', 'e', 'C', 'o',
+ 'd', 'e', '/', 'B',
+ 'a', 'd', 'K', 'i',
+ 'n', 'd', ':', '1',
+ '.', '0', '\0', 0,
+ 0, 0, 0, 0 // no members to this typecode
+};
+
+static CORBA::TypeCode tc_std_BadKind (CORBA::tk_except,
+ sizeof tc_buf_BadKind,
+ tc_buf_BadKind,
+ CORBA::B_FALSE);
+CORBA::TypeCode_ptr CORBA::_tc_BadKind = &tc_std_BadKind;
+
+// Convenience -- say if the exception is a system exception or not.
+
+CORBA::ExceptionType
+CORBA::Environment::exception_type (void) const
+{
+ static char sysex_prefix [] = "IDL:omg.org/CORBA/";
+ static char typecode_extra [] = "TypeCode/";
+
+ if (!_exception)
+ return CORBA::NO_EXCEPTION;
+
+ // All exceptions currently (CORBA 2.0) defined in the CORBA
+ // scope are system exceptions ... except for a couple that
+ // are related to TypeCodes.
+
+ const char *id = _exception->_id ();
+
+ if (ACE_OS::strncmp (id, sysex_prefix, sizeof sysex_prefix - 1) == 0
+ && ACE_OS::strncmp (id + sizeof sysex_prefix - 1,
+ typecode_extra, sizeof typecode_extra - 1) != 0)
+ return CORBA::SYSTEM_EXCEPTION;
+
+ return CORBA::USER_EXCEPTION;
+}
+
+// Diagnostic utility routine: describe the exception onto the
+// standard I/O stream passed as a parameter.
+
+void
+CORBA::Environment::print_exception (const char *info,
+ FILE *) const
+{
+ const char *id = this->_exception->_id ();
+
+ ACE_DEBUG ((LM_ERROR, "(%P|%t) EXCEPTION, %s\n", info));
+
+ // XXX get rid of this logic, and rely on some member function on
+ // Exception to say if it's user or system exception.
+
+ if (ACE_OS::strncmp ((char *) id, "IDL:omg.org/CORBA/", 10) == 0
+ && ACE_OS::strncmp ((char *) id, "IDL:omg.org/CORBA/TypeCode/", 19) != 0)
+ {
+ // XXX this should be a QueryInterface call instead.
+ CORBA::SystemException *x2 =
+ (CORBA::SystemException *) this->_exception;
+
+ // XXX there are a other few "user exceptions" in the CORBA
+ // scope, they're not all standard/system exceptions ... really
+ // need to either compare exhaustively against all those IDs
+ // (yeech) or (preferably) to represent the exception type
+ // directly in the exception value so it can be queried.
+
+ ACE_DEBUG ((LM_ERROR,
+ "(%P|%t) system exception, ID '%s'\n",
+ id));
+ ACE_DEBUG ((LM_ERROR,
+ "(%P|%t) minor code = %x, completed = %s\n",
+ x2->minor (),
+ (x2->completion () == CORBA::COMPLETED_YES) ? "YES" :
+ (x2->completion () == CORBA::COMPLETED_NO) ? "NO" :
+ (x2->completion () == CORBA::COMPLETED_MAYBE) ? "MAYBE" :
+ "garbage"));
+ }
+ else
+ // XXX we can use the exception's typecode to dump all the data
+ // held within it ...
+
+ ACE_DEBUG ((LM_ERROR,
+ "(%P|%t) user exception, ID '%s'\n",
+ id));
+}