Skip to content

Commit

Permalink
Improved native exception handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
ttveldhuis committed Jan 22, 2019
1 parent b2c68ef commit d1c008c
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 163 deletions.
16 changes: 12 additions & 4 deletions JTouchBar.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
771AC5C021F7ACB900BA4322 /* JTouchBarBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 771AC5BE21F7ACB900BA4322 /* JTouchBarBridge.h */; };
771AC5C121F7ACB900BA4322 /* JTouchBarBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 771AC5BF21F7ACB900BA4322 /* JTouchBarBridge.mm */; };
77437EC21F9E849C0064C69F /* JavaTouchBarResponder.h in Headers */ = {isa = PBXBuildFile; fileRef = 77437EC01F9E849C0064C69F /* JavaTouchBarResponder.h */; };
77437EC31F9E849C0064C69F /* JavaTouchBarResponder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 77437EC11F9E849C0064C69F /* JavaTouchBarResponder.mm */; };
77437ECA1F9E84A60064C69F /* JavaTouchBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 77437EC41F9E84A60064C69F /* JavaTouchBar.h */; };
Expand All @@ -18,7 +20,7 @@
77437ED61F9E84B20064C69F /* JTouchBarJNI.h in Headers */ = {isa = PBXBuildFile; fileRef = 77437ED01F9E84B20064C69F /* JTouchBarJNI.h */; };
77437ED91F9E84B20064C69F /* JTouchBarJNI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77437ED31F9E84B20064C69F /* JTouchBarJNI.cpp */; };
77437EDA1F9E84B20064C69F /* JNIContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 77437ED41F9E84B20064C69F /* JNIContext.h */; };
77437EDB1F9E84B20064C69F /* JNIContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77437ED51F9E84B20064C69F /* JNIContext.cpp */; };
77437EDB1F9E84B20064C69F /* JNIContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 77437ED51F9E84B20064C69F /* JNIContext.mm */; };
778F96FF207E0E0C007D0982 /* JavaPopoverTouchBarItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = 778F96FD207E0E0C007D0982 /* JavaPopoverTouchBarItem.mm */; };
778F9700207E0E0C007D0982 /* JavaPopoverTouchBarItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 778F96FE207E0E0C007D0982 /* JavaPopoverTouchBarItem.h */; };
778F9703207E2D89007D0982 /* JTouchBarUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 778F9701207E2D89007D0982 /* JTouchBarUtils.mm */; };
Expand All @@ -28,6 +30,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
771AC5BE21F7ACB900BA4322 /* JTouchBarBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JTouchBarBridge.h; path = "src/main/objective-c++/Bridged/JNI/JTouchBarBridge.h"; sourceTree = "<group>"; };
771AC5BF21F7ACB900BA4322 /* JTouchBarBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JTouchBarBridge.mm; path = "src/main/objective-c++/Bridged/JNI/JTouchBarBridge.mm"; sourceTree = "<group>"; };
77437EC01F9E849C0064C69F /* JavaTouchBarResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaTouchBarResponder.h; path = "src/main/objective-c++/JavaTouchBarResponder.h"; sourceTree = SOURCE_ROOT; };
77437EC11F9E849C0064C69F /* JavaTouchBarResponder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = JavaTouchBarResponder.mm; path = "src/main/objective-c++/JavaTouchBarResponder.mm"; sourceTree = SOURCE_ROOT; };
77437EC41F9E84A60064C69F /* JavaTouchBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaTouchBar.h; path = "src/main/objective-c++/Bridged/JavaTouchBar.h"; sourceTree = SOURCE_ROOT; };
Expand All @@ -39,7 +43,7 @@
77437ED01F9E84B20064C69F /* JTouchBarJNI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JTouchBarJNI.h; path = "src/main/objective-c++/Bridged/JNI/JTouchBarJNI.h"; sourceTree = SOURCE_ROOT; };
77437ED31F9E84B20064C69F /* JTouchBarJNI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JTouchBarJNI.cpp; path = "src/main/objective-c++/Bridged/JNI/JTouchBarJNI.cpp"; sourceTree = SOURCE_ROOT; };
77437ED41F9E84B20064C69F /* JNIContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JNIContext.h; path = "src/main/objective-c++/Bridged/JNI/JNIContext.h"; sourceTree = SOURCE_ROOT; };
77437ED51F9E84B20064C69F /* JNIContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JNIContext.cpp; path = "src/main/objective-c++/Bridged/JNI/JNIContext.cpp"; sourceTree = SOURCE_ROOT; };
77437ED51F9E84B20064C69F /* JNIContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = JNIContext.mm; path = "src/main/objective-c++/Bridged/JNI/JNIContext.mm"; sourceTree = SOURCE_ROOT; };
778F96FD207E0E0C007D0982 /* JavaPopoverTouchBarItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = JavaPopoverTouchBarItem.mm; path = "src/main/objective-c++/Bridged/JavaPopoverTouchBarItem.mm"; sourceTree = "<group>"; };
778F96FE207E0E0C007D0982 /* JavaPopoverTouchBarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaPopoverTouchBarItem.h; path = "src/main/objective-c++/Bridged/JavaPopoverTouchBarItem.h"; sourceTree = "<group>"; };
778F9701207E2D89007D0982 /* JTouchBarUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = JTouchBarUtils.mm; path = "src/main/objective-c++/Bridged/JTouchBarUtils.mm"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -93,7 +97,9 @@
77437EBF1F9E84110064C69F /* JNI */ = {
isa = PBXGroup;
children = (
77437ED51F9E84B20064C69F /* JNIContext.cpp */,
771AC5BF21F7ACB900BA4322 /* JTouchBarBridge.mm */,
771AC5BE21F7ACB900BA4322 /* JTouchBarBridge.h */,
77437ED51F9E84B20064C69F /* JNIContext.mm */,
77437ED41F9E84B20064C69F /* JNIContext.h */,
77437ED31F9E84B20064C69F /* JTouchBarJNI.cpp */,
77437ED01F9E84B20064C69F /* JTouchBarJNI.h */,
Expand Down Expand Up @@ -139,6 +145,7 @@
77437EC21F9E849C0064C69F /* JavaTouchBarResponder.h in Headers */,
778F9700207E0E0C007D0982 /* JavaPopoverTouchBarItem.h in Headers */,
77437ECD1F9E84A60064C69F /* JavaTouchBarItem.h in Headers */,
771AC5C021F7ACB900BA4322 /* JTouchBarBridge.h in Headers */,
77437ECE1F9E84A60064C69F /* JavaGroupTouchBarItem.h in Headers */,
77437EDA1F9E84B20064C69F /* JNIContext.h in Headers */,
77437ED61F9E84B20064C69F /* JTouchBarJNI.h in Headers */,
Expand Down Expand Up @@ -202,14 +209,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
77437EDB1F9E84B20064C69F /* JNIContext.cpp in Sources */,
77437EDB1F9E84B20064C69F /* JNIContext.mm in Sources */,
77437ECF1F9E84A60064C69F /* JavaTouchBarItem.mm in Sources */,
77437EC31F9E849C0064C69F /* JavaTouchBarResponder.mm in Sources */,
778F96FF207E0E0C007D0982 /* JavaPopoverTouchBarItem.mm in Sources */,
778F9703207E2D89007D0982 /* JTouchBarUtils.mm in Sources */,
77437ECB1F9E84A60064C69F /* JavaTouchBar.mm in Sources */,
77437ED91F9E84B20064C69F /* JTouchBarJNI.cpp in Sources */,
77437ECC1F9E84A60064C69F /* JavaGroupTouchBarItem.mm in Sources */,
771AC5C121F7ACB900BA4322 /* JTouchBarBridge.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Binary file modified src/debug/resources/lib/libJTouchBar.dylib
Binary file not shown.
3 changes: 3 additions & 0 deletions src/main/objective-c++/Bridged/JNI/JNIContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#ifndef JNICONTEXT_H
#define JNICONTEXT_H

#import <Foundation/Foundation.h>

#include <jni.h>

#include <vector>
Expand Down Expand Up @@ -68,6 +70,7 @@ class JNIContext {
static image_t CallImageMethod(JNIEnv* env, jobject target, const std::string& method);

static void HandleExceptions(JNIEnv* env);
static void ThrowJavaException(JNIEnv* env, NSException* e);
};

#endif // JNICONTEXT_H
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
*/
#include "JNIContext.h"

#include <Cocoa/Cocoa.h>
#include <JavaVM/JavaVM.h>
#import <Cocoa/Cocoa.h>
#import <JavaVM/JavaVM.h>

#include <map>

Expand Down Expand Up @@ -488,3 +488,23 @@ void JNIContext::HandleExceptions(JNIEnv* env) {
env->ExceptionClear();
}
}

void JNIContext::ThrowJavaException(JNIEnv* env, NSException* e) {
if(env == nullptr) {
return;
}

std::string classname = "java/lang/RuntimeException";
if(e.name == NSInvalidArgumentException) {
classname = "java/lang/IllegalArgumentException";
}

jclass exceptionClass = GetOrFindClass( env, classname.c_str() );
if ( exceptionClass == NULL )
{
return;
}

env->ThrowNew( exceptionClass, [e.description UTF8String] );

}
27 changes: 27 additions & 0 deletions src/main/objective-c++/Bridged/JNI/JTouchBarBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* JTouchBar
*
* Copyright (c) 2018 thizzer.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* @author M. ten Veldhuis
*/
#import <Foundation/Foundation.h>

#include <jni.h>

@interface JTouchBarBridge : NSObject

+(void) setTouchBar:(JNIEnv*)env cls:(jclass)cls viewOrWindowPointerValue:(long)viewOrWindowPointerValue touchBar:(jobject)touchBar;

+(void) updateTouchBarItem:(JNIEnv*)env cls:(jclass)cls itemPointer:(long)itemPointer;

+(void) callObjectSelector:(JNIEnv*)env cls:(jclass)cls objectPointer:(long)objectPointer selector:(jstring)javaSelector onMainThread:(jboolean)onMainThread;

+(int) callIntObjectSelector:(JNIEnv*)env cls:(jclass)cls objectPointer:(long)objectPointer selector:(jstring)javaSelector;

+(long) getAWTViewPointer:(JNIEnv*)env cls:(jclass)cls component:(jobject)component;

@end
213 changes: 213 additions & 0 deletions src/main/objective-c++/Bridged/JNI/JTouchBarBridge.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/**
* JTouchBar
*
* Copyright (c) 2018 thizzer.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* @author M. ten Veldhuis
*/
#import "JTouchBarBridge.h"

#import <Cocoa/Cocoa.h>
#import <JavaVM/JavaVM.h>

#include "JNIContext.h"
#include "JavaTouchBarResponder.h"

static NSMapTable<NSWindow*, JavaTouchBarResponder*> *windowMapping = [NSMapTable weakToStrongObjectsMapTable];

@implementation JTouchBarBridge

+(void) setTouchBar:(JNIEnv*)env cls:(jclass)cls viewOrWindowPointerValue:(long)viewOrWindowPointerValue touchBar:(jobject)touchBar {
@try {
if(viewOrWindowPointerValue == 0) {
return;
}

void* viewOrWindowPointer = (void*) viewOrWindowPointerValue;
NSObject* nsObjectPointer = (__bridge NSObject*) viewOrWindowPointer;
if(nsObjectPointer == nil) {
return;
}

NSWindow *nsWindow = nil;
if([nsObjectPointer isKindOfClass:[NSView class]]) {
NSView *nsView = (NSView*) nsObjectPointer;
if(nsView == nil || ![nsView respondsToSelector:@selector(window)]) {
return;
}

nsWindow = nsView.window;
}
else if([nsObjectPointer isKindOfClass:[NSWindow class]]) {
nsWindow = (NSWindow*) nsObjectPointer;
}
else {
return;
}

if(nsWindow == nil) {
return;
}

JavaTouchBarResponder *jPreviousTouchBarResponder = [windowMapping objectForKey:nsWindow];
if(jPreviousTouchBarResponder == nil && touchBar == nullptr) {
return;
}

if(touchBar == nullptr) {
[jPreviousTouchBarResponder setTouchBar:nil window:nsWindow];
[windowMapping removeObjectForKey:nsWindow];
}
else {
if(jPreviousTouchBarResponder != nil) {
// ensure any old references get destroyed
[jPreviousTouchBarResponder setTouchBar:nil window:nsWindow];
[windowMapping removeObjectForKey:nsWindow];
}

JavaTouchBarResponder *jTouchBarResponder = [[JavaTouchBarResponder alloc] init];
[windowMapping setObject:jTouchBarResponder forKey:nsWindow];

JavaTouchBar *jTouchBar = [[JavaTouchBar alloc] init];
jTouchBar.javaRepr = touchBar;

[jTouchBarResponder setTouchBar:jTouchBar window:nsWindow];
}
}
@catch(NSException* e) {
JNIContext::ThrowJavaException(env, e);
}
}

+(void) updateTouchBarItem:(JNIEnv*)env cls:(jclass)cls itemPointer:(long)itemPointer {
@try {
void* cItemPointer = (void*)itemPointer;
if(cItemPointer == nullptr) {
return;
}

JavaTouchBarItem *touchBarItem = (__bridge JavaTouchBarItem*) (cItemPointer);
if(touchBarItem == nil) {
return;
}

[touchBarItem update];
}
@catch(NSException* e) {
JNIContext::ThrowJavaException(env, e);
}
}

+(void) callObjectSelector:(JNIEnv*)env cls:(jclass)cls objectPointer:(long)objectPointer selector:(jstring)javaSelector onMainThread:(jboolean)onMainThread {
@try {
void* cItemPointer = (void*)objectPointer;
if(cItemPointer == nullptr) {
return;
}

NSObject *touchBarItem = (__bridge NSObject*) (cItemPointer);
if(touchBarItem == nil) {
return;
}

const char *charSelectorValue = env->GetStringUTFChars(javaSelector, 0);
if(charSelectorValue == nullptr) {
return;
}

NSString *selectorStr = [NSString stringWithUTF8String:charSelectorValue];
env->ReleaseStringUTFChars(javaSelector, charSelectorValue);

SEL selector = NSSelectorFromString(selectorStr);
if(selectorStr != nil && [touchBarItem respondsToSelector:selector]) {
if(onMainThread) {
dispatch_async(dispatch_get_main_queue(), ^{
((void (*)(id, SEL))[touchBarItem methodForSelector:selector])(touchBarItem, selector);
});
}
else {
((void (*)(id, SEL))[touchBarItem methodForSelector:selector])(touchBarItem, selector);
}
}
}
@catch(NSException* e) {
JNIContext::ThrowJavaException(env, e);
}
}

+(int) callIntObjectSelector:(JNIEnv*)env cls:(jclass)cls objectPointer:(long)objectPointer selector:(jstring)javaSelector {
@try {
void* cItemPointer = (void*)objectPointer;
if(cItemPointer == nullptr) {
return 0;
}

NSObject *touchBarItem = (__bridge NSObject*) (cItemPointer);
if(touchBarItem == nil) {
return 0;
}

const char *charSelectorValue = env->GetStringUTFChars(javaSelector, 0);
if(charSelectorValue == nullptr) {
return 0;
}

NSString *selectorStr = [NSString stringWithUTF8String:charSelectorValue];
env->ReleaseStringUTFChars(javaSelector, charSelectorValue);

SEL selector = NSSelectorFromString(selectorStr);
if(selectorStr != nil && [touchBarItem respondsToSelector:selector]) {
return ((int (*)(id, SEL))[touchBarItem methodForSelector:selector])(touchBarItem, selector);
}

return 0;
}
@catch(NSException* e) {
JNIContext::ThrowJavaException(env, e);
}
}

+(long) getAWTViewPointer:(JNIEnv*)env cls:(jclass)cls component:(jobject)component {
@try {
jclass componentClass = env->GetObjectClass(component);
jfieldID peerField = env->GetFieldID(componentClass, "peer", "Ljava/awt/peer/ComponentPeer;");
if(peerField == nullptr) {
return 0L;
}

jobject peer = env->GetObjectField(component, peerField);
if(peer == nullptr) {
return 0L;
}

jobject window = JNIContext::CallObjectMethod(env, peer, "getPlatformWindow", "sun/lwawt/PlatformWindow");
if(window == nullptr) {
return 0L;
}

jclass windowClass = env->FindClass("sun/lwawt/macosx/CPlatformWindow");
if(windowClass == nullptr) {
return 0L;
}

jmethodID contentViewMethod = env->GetMethodID(windowClass, "getContentView", "()Lsun/lwawt/macosx/CPlatformView;");
if(contentViewMethod == nullptr) {
return 0L;
}

jobject contentView = env->CallObjectMethod(window, contentViewMethod);
if(contentView == nullptr) {
return 0L;
}

return JNIContext::CallLongMethod(env, contentView, "getAWTView");
}
@catch(NSException* e) {
JNIContext::ThrowJavaException(env, e);
}
}

@end
Loading

0 comments on commit d1c008c

Please sign in to comment.