~tcurdt/sparkle/devel

29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
1
//
2
//  NTSynchronousTask.m
3
//  CocoatechCore
4
//
5
//  Created by Steve Gehrman on 9/29/05.
110 by andym
Major refactoring, yay.
6
//  Copyright 2005 Steve Gehrman. All rights reserved.
29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
7
//
8
59 by andym
Improved headers from Charles D. H. Williams.
9
#import "Sparkle.h"
29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
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];
68 by andym
Numerous minor changes courtesy Sean McBride. Mostly clarifications.
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]];
29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
44
		
68 by andym
Numerous minor changes courtesy Sean McBride. Mostly clarifications.
45
		[[self task] setStandardInput:[self inputPipe]];
46
		[[self task] setStandardOutput:[self outputPipe]];
47
	}
29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
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
	
185 by Andy Matuschak
Fixes 239512
87
	[pool drain];
29 by andym
Finally got DMGs working properly on 10.5 through a somewhat less brittle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.
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