source: trunk/Sparkle/NTSynchronousTask.m @ 1046

Revision 128, 5.8 KB checked in by speck, 4 years ago (diff)

Fixed missing display of update notes in Sparkle. Embedded Sparkle so subversion has the proper version instead of having to download Sparkle and apply several patches.

Line 
1//
2//  NTSynchronousTask.m
3//  CocoatechCore
4//
5//  Created by Steve Gehrman on 9/29/05.
6//  Copyright 2005 Steve Gehrman. All rights reserved.
7//
8
9#import "Sparkle.h"
10#import "NTSynchronousTask.h"
11
12@interface NTSynchronousTask (Private)
13- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
14
15- (NSTask *)task;
16- (void)setTask:(NSTask *)theTask;
17
18- (NSPipe *)outputPipe;
19- (void)setOutputPipe:(NSPipe *)theOutputPipe;
20
21- (NSPipe *)inputPipe;
22- (void)setInputPipe:(NSPipe *)theInputPipe;
23
24- (NSData *)output;
25- (void)setOutput:(NSData *)theOutput;
26
27- (BOOL)done;
28- (void)setDone:(BOOL)flag;
29
30- (int)result;
31- (void)setResult:(int)theResult;
32@end
33
34@implementation NTSynchronousTask
35
36- (id)init;
37{
38    self = [super init];
39    if (self)
40    {
41        [self setTask:[[[NSTask alloc] init] autorelease]];
42        [self setOutputPipe:[[[NSPipe alloc] init] autorelease]];
43        [self setInputPipe:[[[NSPipe alloc] init] autorelease]];
44       
45        [[self task] setStandardInput:[self inputPipe]];
46        [[self task] setStandardOutput:[self outputPipe]];
47    }
48   
49    return self;
50}
51
52//----------------------------------------------------------
53// dealloc
54//----------------------------------------------------------
55- (void)dealloc
56{
57    [[NSNotificationCenter defaultCenter] removeObserver:self];
58
59    [self setTask:nil];
60    [self setOutputPipe:nil];
61    [self setInputPipe:nil];
62    [self setOutput:nil];
63
64    [super dealloc];
65}
66
67+ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
68{
69    // we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased
70    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
71    NSData* result=nil;
72   
73    NS_DURING
74    {
75        NTSynchronousTask* task = [[NTSynchronousTask alloc] init];
76       
77        [task run:toolPath directory:currentDirectory withArgs:args input:input];
78       
79        if ([task result] == 0)
80            result = [[task output] retain];
81               
82        [task release];
83    }   
84    NS_HANDLER;
85    NS_ENDHANDLER;
86   
87    [pool drain];
88   
89    // retained above
90    [result autorelease];
91   
92    return result;
93}
94
95@end
96
97@implementation NTSynchronousTask (Private)
98
99- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
100{
101    BOOL success = NO;
102   
103    if (currentDirectory)
104        [[self task] setCurrentDirectoryPath: currentDirectory];
105   
106    [[self task] setLaunchPath:toolPath];
107    [[self task] setArguments:args];
108               
109    [[NSNotificationCenter defaultCenter] addObserver:self
110                                             selector:@selector(taskOutputAvailable:)
111                                                 name:NSFileHandleReadToEndOfFileCompletionNotification
112                                               object:[[self outputPipe] fileHandleForReading]];
113       
114    [[NSNotificationCenter defaultCenter] addObserver:self
115                                             selector:@selector(taskDidTerminate:)
116                                                 name:NSTaskDidTerminateNotification
117                                               object:[self task]];
118   
119    [[[self outputPipe] fileHandleForReading] readToEndOfFileInBackgroundAndNotifyForModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, nil]];
120   
121    NS_DURING
122        [[self task] launch];
123        success = YES;
124    NS_HANDLER
125        ;
126    NS_ENDHANDLER
127   
128    if (success)
129    {
130        if (input)
131        {
132            // feed the running task our input
133            [[[self inputPipe] fileHandleForWriting] writeData:input];
134            [[[self inputPipe] fileHandleForWriting] closeFile];
135        }
136                       
137        // loop until we are done receiving the data
138        if (![self done])
139        {
140            double resolution = 1;
141            BOOL isRunning;
142            NSDate* next;
143           
144            do {
145                next = [NSDate dateWithTimeIntervalSinceNow:resolution];
146               
147                isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
148                                                     beforeDate:next];
149            } while (isRunning && ![self done]);
150        }
151    }
152}
153
154//----------------------------------------------------------
155//  task
156//----------------------------------------------------------
157- (NSTask *)task
158{
159    return mv_task;
160}
161
162- (void)setTask:(NSTask *)theTask
163{
164    if (mv_task != theTask) {
165        [mv_task release];
166        mv_task = [theTask retain];
167    }
168}
169
170//----------------------------------------------------------
171//  outputPipe
172//----------------------------------------------------------
173- (NSPipe *)outputPipe
174{
175    return mv_outputPipe;
176}
177
178- (void)setOutputPipe:(NSPipe *)theOutputPipe
179{
180    if (mv_outputPipe != theOutputPipe) {
181        [mv_outputPipe release];
182        mv_outputPipe = [theOutputPipe retain];
183    }
184}
185
186//----------------------------------------------------------
187//  inputPipe
188//----------------------------------------------------------
189- (NSPipe *)inputPipe
190{
191    return mv_inputPipe;
192}
193
194- (void)setInputPipe:(NSPipe *)theInputPipe
195{
196    if (mv_inputPipe != theInputPipe) {
197        [mv_inputPipe release];
198        mv_inputPipe = [theInputPipe retain];
199    }
200}
201
202//----------------------------------------------------------
203//  output
204//----------------------------------------------------------
205- (NSData *)output
206{
207    return mv_output;
208}
209
210- (void)setOutput:(NSData *)theOutput
211{
212    if (mv_output != theOutput) {
213        [mv_output release];
214        mv_output = [theOutput retain];
215    }
216}
217
218//----------------------------------------------------------
219//  done
220//----------------------------------------------------------
221- (BOOL)done
222{
223    return mv_done;
224}
225
226- (void)setDone:(BOOL)flag
227{
228    mv_done = flag;
229}
230
231//----------------------------------------------------------
232//  result
233//----------------------------------------------------------
234- (int)result
235{
236    return mv_result;
237}
238
239- (void)setResult:(int)theResult
240{
241    mv_result = theResult;
242}
243
244@end
245
246@implementation NTSynchronousTask (Notifications)
247
248- (void)taskOutputAvailable:(NSNotification*)note
249{
250    [self setOutput:[[note userInfo] objectForKey:NSFileHandleNotificationDataItem]];
251   
252    [self setDone:YES];
253}
254
255- (void)taskDidTerminate:(NSNotification*)note
256{
257    [self setResult:[[self task] terminationStatus]];
258}
259
260@end
261
262
Note: See TracBrowser for help on using the repository browser.