cog/Frameworks/Sparkle/NTSynchronousTask.m

269 lines
6.1 KiB
Objective-C

//
// NTSynchronousTask.m
// CocoatechCore
//
// Created by Steve Gehrman on 9/29/05.
// Copyright 2005 Steve Gehrman. All rights reserved.
//
#import "SUUpdater.h"
#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUVersionComparisonProtocol.h"
#import "NTSynchronousTask.h"
@implementation NTSynchronousTask
//----------------------------------------------------------
// task
//----------------------------------------------------------
- (NSTask *)task
{
return mv_task;
}
- (void)setTask:(NSTask *)theTask
{
if (mv_task != theTask) {
[mv_task release];
mv_task = [theTask retain];
}
}
//----------------------------------------------------------
// outputPipe
//----------------------------------------------------------
- (NSPipe *)outputPipe
{
return mv_outputPipe;
}
- (void)setOutputPipe:(NSPipe *)theOutputPipe
{
if (mv_outputPipe != theOutputPipe) {
[mv_outputPipe release];
mv_outputPipe = [theOutputPipe retain];
}
}
//----------------------------------------------------------
// inputPipe
//----------------------------------------------------------
- (NSPipe *)inputPipe
{
return mv_inputPipe;
}
- (void)setInputPipe:(NSPipe *)theInputPipe
{
if (mv_inputPipe != theInputPipe) {
[mv_inputPipe release];
mv_inputPipe = [theInputPipe retain];
}
}
//----------------------------------------------------------
// output
//----------------------------------------------------------
- (NSData *)output
{
return mv_output;
}
- (void)setOutput:(NSData *)theOutput
{
if (mv_output != theOutput) {
[mv_output release];
mv_output = [theOutput retain];
}
}
//----------------------------------------------------------
// done
//----------------------------------------------------------
- (BOOL)done
{
return mv_done;
}
- (void)setDone:(BOOL)flag
{
mv_done = flag;
}
//----------------------------------------------------------
// result
//----------------------------------------------------------
- (int)result
{
return mv_result;
}
- (void)setResult:(int)theResult
{
mv_result = theResult;
}
- (void)taskOutputAvailable:(NSNotification*)note
{
[self setOutput:[[note userInfo] objectForKey:NSFileHandleNotificationDataItem]];
[self setDone:YES];
}
- (void)taskDidTerminate:(NSNotification*)note
{
[self setResult:[[self task] terminationStatus]];
}
- (id)init;
{
self = [super init];
if (self)
{
[self setTask:[[[NSTask alloc] init] autorelease]];
[self setOutputPipe:[[[NSPipe alloc] init] autorelease]];
[self setInputPipe:[[[NSPipe alloc] init] autorelease]];
[[self task] setStandardInput:[self inputPipe]];
[[self task] setStandardOutput:[self outputPipe]];
[[self task] setStandardError:[self outputPipe]];
}
return self;
}
//----------------------------------------------------------
// dealloc
//----------------------------------------------------------
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[mv_task release];
[mv_outputPipe release];
[mv_inputPipe release];
[mv_output release];
[super dealloc];
}
- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input
{
BOOL success = NO;
if (currentDirectory)
[[self task] setCurrentDirectoryPath: currentDirectory];
[[self task] setLaunchPath:toolPath];
[[self task] setArguments:args];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(taskOutputAvailable:)
name:NSFileHandleReadToEndOfFileCompletionNotification
object:[[self outputPipe] fileHandleForReading]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(taskDidTerminate:)
name:NSTaskDidTerminateNotification
object:[self task]];
[[[self outputPipe] fileHandleForReading] readToEndOfFileInBackgroundAndNotifyForModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, nil]];
@try
{
[[self task] launch];
success = YES;
}
@catch (NSException *localException) { }
if (success)
{
if (input)
{
// feed the running task our input
[[[self inputPipe] fileHandleForWriting] writeData:input];
[[[self inputPipe] fileHandleForWriting] closeFile];
}
// loop until we are done receiving the data
if (![self done])
{
double resolution = 1;
BOOL isRunning;
NSDate* next;
do {
next = [NSDate dateWithTimeIntervalSinceNow:resolution];
isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:next];
} while (isRunning && ![self done]);
}
}
}
+ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input
{
// we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData* result=nil;
@try
{
NTSynchronousTask* task = [[NTSynchronousTask alloc] init];
[task run:toolPath directory:currentDirectory withArgs:args input:input];
if ([task result] == 0)
result = [[task output] retain];
[task release];
}
@catch (NSException *localException) { }
[pool drain];
// retained above
[result autorelease];
return result;
}
+(int) task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input output: (NSData**)outData
{
// we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int taskResult = 0;
if( outData )
*outData = nil;
NS_DURING
{
NTSynchronousTask* task = [[NTSynchronousTask alloc] init];
[task run:toolPath directory:currentDirectory withArgs:args input:input];
taskResult = [task result];
if( outData )
*outData = [[task output] retain];
[task release];
}
NS_HANDLER;
taskResult = errCppGeneral;
NS_ENDHANDLER;
[pool drain];
// retained above
if( outData )
[*outData autorelease];
return taskResult;
}
@end