Best effort to print more details about caught UNO exception
Change-Id: Ia8f098e4e441b6aba0d76d7184dc6cec2210f793 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173813 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
This commit is contained in:
parent
a593c27e88
commit
7ccfc0277a
2 changed files with 130 additions and 12 deletions
|
@ -13,6 +13,7 @@ $(eval $(call gb_Library_Library,unoexceptionprotector))
|
||||||
$(eval $(call gb_Library_use_sdk_api,unoexceptionprotector))
|
$(eval $(call gb_Library_use_sdk_api,unoexceptionprotector))
|
||||||
|
|
||||||
$(eval $(call gb_Library_use_libraries,unoexceptionprotector,\
|
$(eval $(call gb_Library_use_libraries,unoexceptionprotector,\
|
||||||
|
comphelper \
|
||||||
cppu \
|
cppu \
|
||||||
cppuhelper \
|
cppuhelper \
|
||||||
sal \
|
sal \
|
||||||
|
|
|
@ -17,16 +17,27 @@
|
||||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <string>
|
#include <iomanip>
|
||||||
#include <string_view>
|
#include <ios>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <com/sun/star/reflection/XIdlReflection.hpp>
|
||||||
|
#include <com/sun/star/reflection/XIdlClass.hpp>
|
||||||
|
#include <com/sun/star/reflection/theCoreReflection.hpp>
|
||||||
#include <com/sun/star/uno/Any.hxx>
|
#include <com/sun/star/uno/Any.hxx>
|
||||||
#include <com/sun/star/uno/Exception.hpp>
|
#include <com/sun/star/uno/Exception.hpp>
|
||||||
|
#include <com/sun/star/uno/Reference.hxx>
|
||||||
|
#include <com/sun/star/uno/Type.hxx>
|
||||||
|
#include <com/sun/star/uno/TypeClass.hpp>
|
||||||
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
||||||
|
#include <comphelper/processfactory.hxx>
|
||||||
#include <cppuhelper/exc_hlp.hxx>
|
#include <cppuhelper/exc_hlp.hxx>
|
||||||
#include <cppunit/Message.h>
|
#include <cppunit/Message.h>
|
||||||
#include <osl/thread.h>
|
#include <o3tl/any.hxx>
|
||||||
#include <rtl/string.hxx>
|
#include <o3tl/unreachable.hxx>
|
||||||
#include <rtl/ustring.hxx>
|
#include <rtl/ustring.hxx>
|
||||||
#include <sal/types.h>
|
#include <sal/types.h>
|
||||||
|
|
||||||
|
@ -34,12 +45,106 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Best effort conversion:
|
css::uno::Type translateType(css::uno::Reference<css::reflection::XIdlClass> const & type) {
|
||||||
std::string convert(std::u16string_view s16) {
|
return css::uno::Type(type->getTypeClass(), type->getName());
|
||||||
OString s8(OUStringToOString(s16, osl_getThreadTextEncoding()));
|
}
|
||||||
static_assert(sizeof (sal_Int32) <= sizeof (std::string::size_type), "got to be at least equal");
|
|
||||||
// ensure following cast is legitimate
|
void printUnoValue(
|
||||||
return std::string(s8);
|
std::ostream & out, css::uno::Reference<css::reflection::XIdlReflection> const & reflections,
|
||||||
|
css::uno::Type const & type, css::uno::Any const & value)
|
||||||
|
{
|
||||||
|
switch (type.getTypeClass()) {
|
||||||
|
case css::uno::TypeClass_VOID:
|
||||||
|
out << "void";
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_BOOLEAN:
|
||||||
|
out << *o3tl::forceAccess<bool>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_BYTE:
|
||||||
|
out << int(*o3tl::forceAccess<sal_Int8>(value));
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_SHORT:
|
||||||
|
out << *o3tl::forceAccess<sal_Int16>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_UNSIGNED_SHORT:
|
||||||
|
out << *o3tl::forceAccess<sal_uInt16>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_LONG:
|
||||||
|
out << *o3tl::forceAccess<sal_Int32>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_UNSIGNED_LONG:
|
||||||
|
out << *o3tl::forceAccess<sal_uInt32>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_HYPER:
|
||||||
|
out << *o3tl::forceAccess<sal_Int64>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_UNSIGNED_HYPER:
|
||||||
|
out << *o3tl::forceAccess<sal_uInt64>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_FLOAT:
|
||||||
|
out << std::uppercase << *o3tl::forceAccess<float>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_DOUBLE:
|
||||||
|
out << std::uppercase << *o3tl::forceAccess<double>(value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_CHAR:
|
||||||
|
out << "\\u" << std::hex << std::uppercase << std::setw(4) << std::setfill('0')
|
||||||
|
<< std::uint_least16_t(*o3tl::forceAccess<char16_t>(value)) << std::dec;
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_STRING:
|
||||||
|
out << '"' << *o3tl::forceAccess<OUString>(value) << '"'; //TODO: encode content
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_TYPE:
|
||||||
|
out << o3tl::forceAccess<css::uno::Type>(value)->getTypeName();
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_ANY:
|
||||||
|
out << value.getValueTypeName() << ": ";
|
||||||
|
printUnoValue(out, reflections, value.getValueType(), value);
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_SEQUENCE:
|
||||||
|
{
|
||||||
|
css::uno::Reference<css::reflection::XIdlClass> const refl(
|
||||||
|
reflections->forName(type.getTypeName()), css::uno::UNO_SET_THROW);
|
||||||
|
auto const t = translateType(refl->getComponentType());
|
||||||
|
auto const array = refl->getArray();
|
||||||
|
auto const n = array->getLen(value);
|
||||||
|
out << '[';
|
||||||
|
for (sal_Int32 i = 0; i != n; ++i) {
|
||||||
|
if (i != 0) {
|
||||||
|
out << ", ";
|
||||||
|
}
|
||||||
|
printUnoValue(out, reflections, t, array->get(value, i));
|
||||||
|
}
|
||||||
|
out << ']';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case css::uno::TypeClass_ENUM:
|
||||||
|
out << value.getValueTypeName() << ' ' << *static_cast<sal_Int32 const *>(value.getValue());
|
||||||
|
break;
|
||||||
|
case css::uno::TypeClass_STRUCT:
|
||||||
|
case css::uno::TypeClass_EXCEPTION:
|
||||||
|
{
|
||||||
|
auto first = true;
|
||||||
|
for (auto const & f: css::uno::Reference<css::reflection::XIdlClass>(
|
||||||
|
reflections->forName(type.getTypeName()),
|
||||||
|
css::uno::UNO_SET_THROW)->getFields())
|
||||||
|
{
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
out << ", ";
|
||||||
|
}
|
||||||
|
out << f->getName() << ": ";
|
||||||
|
printUnoValue(out, reflections, translateType(f->getType()), f->get(value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case css::uno::TypeClass_INTERFACE:
|
||||||
|
out << '@' << value.getValue();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
O3TL_UNREACHABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Prot : public CppUnit::Protector
|
class Prot : public CppUnit::Protector
|
||||||
|
@ -62,11 +167,23 @@ bool Prot::protect(
|
||||||
return functor();
|
return functor();
|
||||||
} catch (const css::uno::Exception &e) {
|
} catch (const css::uno::Exception &e) {
|
||||||
css::uno::Any a(cppu::getCaughtException());
|
css::uno::Any a(cppu::getCaughtException());
|
||||||
|
std::ostringstream s;
|
||||||
|
try {
|
||||||
|
printUnoValue(
|
||||||
|
s,
|
||||||
|
css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext()),
|
||||||
|
cppu::UnoType<css::uno::Any>::get(), a);
|
||||||
|
} catch (css::uno::Exception &) {
|
||||||
|
// Best effort to print full details above; if that fails for whatever reason, print as
|
||||||
|
// much detailed information as possible, followed by at least the exception type and
|
||||||
|
// message:
|
||||||
|
s << "... " << a.getValueTypeName() << ": " << e.Message;
|
||||||
|
}
|
||||||
reportError(
|
reportError(
|
||||||
context,
|
context,
|
||||||
CppUnit::Message(
|
CppUnit::Message(
|
||||||
"An uncaught exception of type " + convert(a.getValueTypeName()),
|
"An uncaught UNO exception",
|
||||||
convert(e.Message)));
|
s.str()));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue