diff options
author | Noel Grandin <noel@peralex.com> | 2014-08-15 16:17:25 +0200 |
---|---|---|
committer | Noel Grandin <noel@peralex.com> | 2014-09-25 13:47:25 +0200 |
commit | 83636d2c09802aeeb1b30078022d228d04da21eb (patch) | |
tree | 8a0c619e16c1f6b5388939d5da2956f7ef758c19 /codemaker | |
parent | cf49392511e98851174b353782df9eb6bac46f77 (diff) |
java: when rethrowing exceptions, store the original cause
so that we get a nice complete stacktrace when it hits the final
handler
Change-Id: Iec4fcc15a2a25c55f591b5e069dce3d010197a90
Diffstat (limited to 'codemaker')
-rw-r--r-- | codemaker/source/javamaker/javatype.cxx | 137 |
1 files changed, 129 insertions, 8 deletions
diff --git a/codemaker/source/javamaker/javatype.cxx b/codemaker/source/javamaker/javatype.cxx index 9e08171bb07d..5d026449b0f6 100644 --- a/codemaker/source/javamaker/javatype.cxx +++ b/codemaker/source/javamaker/javatype.cxx @@ -1672,6 +1672,8 @@ void handleExceptionType( i->name, index++); } } + + // create default constructor SAL_WNODEPRECATED_DECLARATIONS_PUSH std::auto_ptr< ClassFile::Code > code(cf->newCode()); SAL_WNODEPRECATED_DECLARATIONS_POP @@ -1702,6 +1704,78 @@ void handleExceptionType( cf->addMethod( ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(), std::vector< OString >(), ""); + + + // create (Throwable Cause) constructor + code.reset(cf->newCode()); + code->loadLocalReference(0); + code->loadLocalReference(1); + code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;)V"); + stack = 0; + if (baseRuntimeException) { + stack = std::max( + stack, + addFieldInit( + manager, className, "Context", false, + "com.sun.star.uno.XInterface", dependencies, code.get())); + } + for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i( + entity->getDirectMembers().begin()); + i != entity->getDirectMembers().end(); ++i) + { + if (!baseException || i != entity->getDirectMembers().begin()) { + stack = std::max( + stack, + addFieldInit( + manager, className, i->name, false, i->type, dependencies, + code.get())); + } + } + code->instrReturn(); + code->setMaxStackAndLocals(stack + 2, 2); + cf->addMethod( + ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;)V", code.get(), + std::vector< OString >(), ""); + + // create (Throwable Cause, String Message) constructor + code.reset(cf->newCode()); + code->loadLocalReference(0); + if (baseException || baseRuntimeException) { + code->loadLocalReference(2); + code->loadLocalReference(1); + code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V"); + } else { + code->loadLocalReference(1); + code->loadLocalReference(2); + code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V"); + } + stack = 0; + if (baseRuntimeException) { + stack = std::max( + stack, + addFieldInit( + manager, className, "Context", false, + "com.sun.star.uno.XInterface", dependencies, code.get())); + } + for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i( + entity->getDirectMembers().begin()); + i != entity->getDirectMembers().end(); ++i) + { + if (!baseException || i != entity->getDirectMembers().begin()) { + stack = std::max( + stack, + addFieldInit( + manager, className, i->name, false, i->type, dependencies, + code.get())); + } + } + code->instrReturn(); + code->setMaxStackAndLocals(stack + 3, 3); + cf->addMethod( + ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V", code.get(), + std::vector< OString >(), ""); + + // create (String Message) constructor code.reset(cf->newCode()); code->loadLocalReference(0); code->loadLocalReference(1); @@ -1731,24 +1805,27 @@ void handleExceptionType( cf->addMethod( ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", code.get(), std::vector< OString >(), ""); - MethodDescriptor desc(manager, dependencies, "void", 0, 0); + + + // create (String Message, Object Context, T1 m1, ..., Tn mn) constructor + MethodDescriptor desc1(manager, dependencies, "void", 0, 0); code.reset(cf->newCode()); code->loadLocalReference(0); sal_uInt16 index2 = 1; - desc.addParameter("string", false, true, 0); code->loadLocalReference(index2++); + desc1.addParameter("string", false, true, 0); if (!(baseException || baseRuntimeException)) { addExceptionBaseArguments( - manager, dependencies, &desc, code.get(), entity->getDirectBase(), + manager, dependencies, &desc1, code.get(), entity->getDirectBase(), &index2); } - code->instrInvokespecial(superClass, "<init>", desc.getDescriptor()); + code->instrInvokespecial(superClass, "<init>", desc1.getDescriptor()); sal_uInt16 maxSize = index2; if (baseRuntimeException) { maxSize = std::max( maxSize, addDirectArgument( - manager, dependencies, &desc, code.get(), &index2, className, + manager, dependencies, &desc1, code.get(), &index2, className, "Context", false, "com.sun.star.uno.XInterface")); } for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i( @@ -1759,7 +1836,7 @@ void handleExceptionType( maxSize = std::max( maxSize, addDirectArgument( - manager, dependencies, &desc, code.get(), &index2, + manager, dependencies, &desc1, code.get(), &index2, className, codemaker::convertString(i->name), false, i->type)); } @@ -1767,8 +1844,52 @@ void handleExceptionType( code->instrReturn(); code->setMaxStackAndLocals(maxSize, index2); cf->addMethod( - ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(), - std::vector< OString >(), desc.getSignature()); + ClassFile::ACC_PUBLIC, "<init>", desc1.getDescriptor(), code.get(), + std::vector< OString >(), desc1.getSignature()); + + // create (Throwable Cause, String Message, Object Context, T1 m1, ..., Tn mn) constructor + MethodDescriptor desc2(manager, dependencies, "void", 0, 0); + code.reset(cf->newCode()); + code->loadLocalReference(0); + sal_uInt16 index3 = 1; + code->loadLocalReference(index3++); + code->loadLocalReference(index3++); + // Note that we hack in the java.lang.Throwable parameter further down, + // because MethodDescriptor does not know how to handle it. + desc2.addParameter("string", false, true, 0); + if (!(baseException || baseRuntimeException)) { + addExceptionBaseArguments( + manager, dependencies, &desc2, code.get(), entity->getDirectBase(), + &index3); + } + code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1)); + sal_uInt16 maxSize2 = index3; + if (baseRuntimeException) { + maxSize2 = std::max( + maxSize2, + addDirectArgument( + manager, dependencies, &desc2, code.get(), &index3, className, + "Context", false, "com.sun.star.uno.XInterface")); + } + for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i( + entity->getDirectMembers().begin()); + i != entity->getDirectMembers().end(); ++i) + { + if (!baseException || i != entity->getDirectMembers().begin()) { + maxSize2 = std::max( + maxSize2, + addDirectArgument( + manager, dependencies, &desc2, code.get(), &index3, + className, codemaker::convertString(i->name), false, + i->type)); + } + } + code->instrReturn(); + code->setMaxStackAndLocals(maxSize2, index3); + cf->addMethod( + ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1), code.get(), + std::vector< OString >(), desc2.getSignature()); + addTypeInfo(className, typeInfo, dependencies, cf.get()); writeClassFile(options, className, *cf.get()); } |