summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorMichi Henning <michi@zeroc.com>2004-09-01 04:10:44 +0000
committerMichi Henning <michi@zeroc.com>2004-09-01 04:10:44 +0000
commitd9c1f63c51255ca2dfffe34aa610a08a29f14533 (patch)
tree32513e61aad5e2ea17633710f5078aca254b1891 /cpp/src
parentRenamed IceInternal::Connection to Ice::ConnectionI (diff)
downloadice-d9c1f63c51255ca2dfffe34aa610a08a29f14533.tar.bz2
ice-d9c1f63c51255ca2dfffe34aa610a08a29f14533.tar.xz
ice-d9c1f63c51255ca2dfffe34aa610a08a29f14533.zip
Changed generated code to make it impossible for a client to receive an
"impossible" exception if client and server are compiled with mismatched exception specifications for an operation.
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/slice2cpp/Gen.cpp70
1 files changed, 68 insertions, 2 deletions
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 1ad5b03a644..e214f8e1f7e 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -1577,6 +1577,50 @@ Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p)
C << nl << "return __ret;";
}
C << eb;
+
+ //
+ // Generate a catch block for each legal user exception. This is necessary
+ // to prevent an "impossible" user exception to be thrown if client and
+ // and server use different exception specifications for an operation. For
+ // example:
+ //
+ // Client compiled with:
+ // exception A {};
+ // exception B {};
+ // interface I {
+ // void op() throws A;
+ // };
+ //
+ // Server compiled with:
+ // exception A {};
+ // exception B {};
+ // interface I {
+ // void op() throws B; // Differs from client
+ // };
+ //
+ // We need the catch blocks so, if the server throws B from op(), the
+ // client receives UnknownUserException instead of B.
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+ for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
+ {
+ string scoped = (*i)->scoped();
+ C << nl << "catch(const " << (*i)->scoped() << "&)";
+ C << sb;
+ C << nl << "throw;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::UserException&)";
+ C << sb;
+ C << nl << "throw ::Ice::UnknownUserException(__FILE__, __LINE__);";
+ C << eb;
C << nl << "catch(const ::Ice::LocalException& __ex)";
C << sb;
C << nl << "throw ::IceInternal::NonRepeatable(__ex);";
@@ -3518,9 +3562,31 @@ Slice::Gen::AsyncVisitor::visitOperation(const OperationPtr& p)
C << nl << "__finished(__ex);";
C << nl << "return;";
C << eb;
- C << nl << "catch(const ::Ice::UserException& __ex)";
+
+ //
+ // Generate a catch block for each legal user exception.
+ // (See comment in DelegateMVisitor::visitOperation() for details.)
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+#if defined(__SUNPRO_CC)
+ throws.sort(derivedToBaseCompare);
+#else
+ throws.sort(Slice::DerivedToBaseCompare());
+#endif
+ for(ExceptionList::const_iterator i = throws.begin(); i != throws.end(); ++i)
+ {
+ string scoped = (*i)->scoped();
+ C << nl << "catch(const " << (*i)->scoped() << "& __ex)";
+ C << sb;
+ C << nl << "ice_exception(__ex);";
+ C << nl << "return;";
+ C << eb;
+ }
+ C << nl << "catch(const ::Ice::UserException&)";
C << sb;
- C << nl << "ice_exception(__ex);";
+ C << nl << "ice_exception(::Ice::UnknownUserException(__FILE__, __LINE__));";
C << nl << "return;";
C << eb;
C << nl << "ice_response" << spar << args << epar << ';';