Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/apple/applescript/AppleScriptExecutionContext.m
38829 views
/*1* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import "AppleScriptExecutionContext.h"2627#import <Carbon/Carbon.h>2829#import "AS_NS_ConversionUtils.h"303132@implementation AppleScriptExecutionContext3334@synthesize source;35@synthesize context;36@synthesize error;37@synthesize returnValue;3839- (id) init:(NSString *)sourceIn context:(id)contextIn {40self = [super init];41if (!self) return self;4243self.source = sourceIn;44self.context = contextIn;45self.returnValue = nil;46self.error = nil;4748return self;49}5051- (id) initWithSource:(NSString *)sourceIn context:(NSDictionary *)contextIn {52self = [self init:sourceIn context:contextIn];53isFile = NO;54return self;55}5657- (id) initWithFile:(NSString *)filenameIn context:(NSDictionary *)contextIn {58self = [self init:filenameIn context:contextIn];59isFile = YES;60return self;61}6263- (void) dealloc {64self.source = nil;65self.context = nil;66self.returnValue = nil;67self.error = nil;6869[super dealloc];70}7172- (NSAppleScript *) scriptFromURL {73NSURL *url = [NSURL URLWithString:source];74NSDictionary *err = nil;75NSAppleScript *script = [[[NSAppleScript alloc] initWithContentsOfURL:url error:(&err)] autorelease];76if (err != nil) self.error = err;77return script;78}7980- (NSAppleScript *) scriptFromSource {81return [[[NSAppleScript alloc] initWithSource:source] autorelease];82}8384- (NSAppleEventDescriptor *) functionInvocationEvent {85NSString *function = [[context objectForKey:@"javax_script_function"] description];86if (function == nil) return nil;8788// wrap the arg in an array if it is not already a list89id args = [context objectForKey:@"javax_script_argv"];90if (![args isKindOfClass:[NSArray class]]) {91args = [NSArray arrayWithObjects:args, nil];92}9394// triangulate our target95int pid = [[NSProcessInfo processInfo] processIdentifier];96NSAppleEventDescriptor* targetAddress = [NSAppleEventDescriptor descriptorWithDescriptorType:typeKernelProcessID97bytes:&pid98length:sizeof(pid)];99100// create the event to call a subroutine in the script101NSAppleEventDescriptor* event = [[NSAppleEventDescriptor alloc] initWithEventClass:kASAppleScriptSuite102eventID:kASSubroutineEvent103targetDescriptor:targetAddress104returnID:kAutoGenerateReturnID105transactionID:kAnyTransactionID];106107// set up the handler108NSAppleEventDescriptor* subroutineDescriptor = [NSAppleEventDescriptor descriptorWithString:[function lowercaseString]];109[event setParamDescriptor:subroutineDescriptor forKeyword:keyASSubroutineName];110111// set up the arguments112[event setParamDescriptor:[args aeDescriptorValue] forKeyword:keyDirectObject];113114return [event autorelease];115}116117- (void) invoke {118// create our script119NSAppleScript *script = isFile ? [self scriptFromURL] : [self scriptFromSource];120if (self.error != nil) return;121122// find out if we have a subroutine to call123NSAppleEventDescriptor *fxnInvkEvt = [self functionInvocationEvent];124125// exec!126NSAppleEventDescriptor *desc = nil;127NSDictionary *err = nil;128if (fxnInvkEvt == nil) {129desc = [script executeAndReturnError:(&err)];130} else {131desc = [script executeAppleEvent:fxnInvkEvt error:(&err)];132}133134// if we encountered an exception, stash and bail135if (err != nil) {136self.error = err;137return;138}139140// convert to NSObjects, and return in ivar141self.returnValue = [desc objCObjectValue];142}143144- (id) invokeWithEnv:(JNIEnv *)env {145BOOL useAnyThread = [@"any-thread" isEqual:[context valueForKey:@"javax_script_threading"]];146147// check if we are already on the AppKit thread, if desired148if(pthread_main_np() || useAnyThread) {149[self invoke];150} else {151[JNFRunLoop performOnMainThread:@selector(invoke) on:self withObject:nil waitUntilDone:YES];152}153154// if we have an exception parked in our ivar, snarf the message (if there is one), and toss a ScriptException155if (self.error != nil) {156NSString *asErrString = [self.error objectForKey:NSAppleScriptErrorMessage];157if (!asErrString) asErrString = @"AppleScriptEngine failed to execute script."; // usually when we fail to load a file158[JNFException raise:env as:"javax/script/ScriptException" reason:[asErrString UTF8String]];159}160161return self.returnValue;162}163164@end165166167