| // Test to check the exception classes in the throws attribute of the typemaps and except feature is working | |
| %module java_throws | |
| // throw is invalid in C++17 and later, only SWIG to use it | |
| #define TESTCASE_THROW1(T1) throw(T1) | |
| %{ | |
| #define TESTCASE_THROW1(T1) | |
| %} | |
| // Exceptions are chosen at random but are ones which have to have a try catch block to compile | |
| %typemap(in, throws=" ClassNotFoundException") int num { | |
| $1 = (int)$input; | |
| } | |
| %typemap(freearg, throws="InstantiationException ") int num "/*not written*/" | |
| %typemap(argout, throws="CloneNotSupportedException ") int num "/*not written*/" | |
| %typemap(check, throws="NoSuchFieldException") int num { | |
| if ($input == 10) { | |
| jenv->ExceptionClear(); | |
| jclass excep = jenv->FindClass("java/lang/NoSuchFieldException"); | |
| if (excep) | |
| jenv->ThrowNew(excep, "Value of 10 not acceptable"); | |
| return $null; | |
| } | |
| } | |
| // Duplicate exceptions should be removed from the generated throws clause | |
| %typemap(out, throws="IllegalAccessException, NoSuchFieldException, CloneNotSupportedException ") short { | |
| $result = (jshort)$1; | |
| } | |
| %inline %{ | |
| short full_of_exceptions(int num) { | |
| return 0; | |
| } | |
| %} | |
| %typemap(throws, throws="IllegalAccessException") int { | |
| (void)$1; | |
| jclass excep = jenv->FindClass("java/lang/IllegalAccessException"); | |
| if (excep) { | |
| jenv->ThrowNew(excep, "Test exception"); | |
| } | |
| return $null; | |
| } | |
| %inline %{ | |
| bool throw_spec_function(int value) TESTCASE_THROW1(int) { throw (int)0; } | |
| %} | |
| %catches(int) catches_function(int value); | |
| %inline %{ | |
| bool catches_function(int value) { throw (int)0; } | |
| %} | |
| // Check newfree typemap throws attribute | |
| %newobject makeTestClass; | |
| %typemap(newfree, throws="NoSuchMethodException") TestClass* "/*not written*/" | |
| %inline %{ | |
| class TestClass { | |
| int x; | |
| public: | |
| TestClass(int xx) : x(xx) {} | |
| }; | |
| TestClass* makeTestClass() { return new TestClass(1000); } | |
| %} | |
| // javain typemap throws attribute | |
| // Will only compile if the fileFunction has a java.io.IOException throws clause as getCanonicalPath() throws this exception | |
| %typemap(jstype) char* someFileArgument "java.io.File" | |
| %typemap(javain, throws="java.io.IOException") char* someFileArgument "$javainput.getCanonicalPath()" | |
| %inline %{ | |
| void fileFunction(char* someFileArgument) {} | |
| %} | |
| // javout typemap throws attribute | |
| %typemap(javaout, throws="java.io.IOException") int { | |
| int returnValue=$jnicall; | |
| if (returnValue==0) throw new java.io.IOException("some IOException"); | |
| return returnValue; | |
| } | |
| %inline %{ | |
| int ioTest() { return 0; } | |
| %} | |
| // except feature (%javaexception) specifying a checked exception class for the throws clause | |
| %typemap(javabase) MyException "Throwable" | |
| %typemap(javacode) MyException %{ | |
| public static final long serialVersionUID = 0x52151000; // Suppress ecj warning | |
| %} | |
| %inline %{ | |
| struct MyException { | |
| MyException(const char *msg) {} | |
| }; | |
| %} | |
| %define JAVAEXCEPTION(METHOD) | |
| %javaexception("MyException") METHOD %{ | |
| try { | |
| $action | |
| } catch (MyException) { | |
| jclass excep = jenv->FindClass("java_throws/MyException"); | |
| if (excep) | |
| jenv->ThrowNew(excep, "exception message"); | |
| return $null; | |
| } | |
| %} | |
| %enddef | |
| JAVAEXCEPTION(FeatureTest::FeatureTest) | |
| JAVAEXCEPTION(FeatureTest::method) | |
| JAVAEXCEPTION(FeatureTest::staticMethod) | |
| %inline %{ | |
| struct FeatureTest { | |
| static void staticMethod() { | |
| throw MyException("no message"); | |
| } | |
| void method() { | |
| throw MyException("no message"); | |
| } | |
| }; | |
| %} | |
| %include <swiginterface.i> | |
| %interface_impl(InterfaceTest); | |
| JAVAEXCEPTION(imethod) | |
| %inline %{ | |
| struct InterfaceTest { | |
| virtual void imethod(bool raise) = 0; | |
| virtual ~InterfaceTest() {} | |
| }; | |
| struct InterfaceTestImpl : InterfaceTest { | |
| void imethod(bool raise) { | |
| if (raise) | |
| throw MyException("raise message"); | |
| } | |
| }; | |
| %} | |
| // Mixing except feature and typemaps when both generate a class for the throws clause | |
| %typemap(in, throws="ClassNotFoundException") int both { | |
| $1 = (int)$input; | |
| } | |
| %javaexception("MyException , NoSuchFieldException") globalFunction %{ | |
| try { | |
| $action | |
| } catch (MyException) { | |
| jclass excep = jenv->FindClass("java_throws/MyException"); | |
| if (excep) | |
| jenv->ThrowNew(excep, "exception message"); | |
| return $null; | |
| } | |
| %} | |
| %inline %{ | |
| void globalFunction(int both) { | |
| throw MyException("no message"); | |
| } | |
| %} | |
| // Test %nojavaexception | |
| %javaexception("MyException") %{ | |
| /* global exception handler */ | |
| try { | |
| $action | |
| } catch (MyException) { | |
| jclass excep = jenv->FindClass("java_throws/MyException"); | |
| if (excep) | |
| jenv->ThrowNew(excep, "exception message"); | |
| return $null; | |
| } | |
| %} | |
| %nojavaexception *::noExceptionPlease(); | |
| %nojavaexception NoExceptTest::NoExceptTest(); | |
| // Need to handle the checked exception in NoExceptTest.delete() | |
| %typemap(javafinalize) SWIGTYPE %{ | |
| @SuppressWarnings({"deprecation", "removal"}) | |
| protected void finalize() { | |
| try { | |
| delete(); | |
| } catch (MyException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| %} | |
| %typemap(javabody) SWIGTYPE %{ | |
| private transient long swigCPtr; | |
| protected transient boolean swigCMemOwn; | |
| protected $javaclassname(long cPtr, boolean cMemoryOwn) { | |
| swigCMemOwn = cMemoryOwn; | |
| swigCPtr = cPtr; | |
| } | |
| protected static long getCPtr($javaclassname obj) { | |
| return (obj == null) ? 0 : obj.swigCPtr; | |
| } | |
| protected static long swigRelease($javaclassname obj) { | |
| long ptr = 0; | |
| if (obj != null) { | |
| if (!obj.swigCMemOwn) | |
| throw new RuntimeException("Cannot release ownership as memory is not owned"); | |
| ptr = obj.swigCPtr; | |
| obj.swigCMemOwn = false; | |
| try { | |
| obj.delete(); | |
| } catch (MyException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| return ptr; | |
| } | |
| %} | |
| %inline %{ | |
| struct NoExceptTest { | |
| unsigned int noExceptionPlease() { return 123; } | |
| unsigned int exceptionPlease() { return 456; } | |
| ~NoExceptTest() {} | |
| }; | |
| %} | |
| // Turn global exceptions off (for the implicit destructors/constructors) | |
| %nojavaexception; | |