~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/NSDistributedNotificationCenter.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** Implementation of NSDistributedNotificationCenter class
2
 
   Copyright (C) 1998 Free Software Foundation, Inc.
 
1
/**
 
2
   Copyright (C) 1998-2003 Free Software Foundation, Inc.
3
3
 
4
4
   Written by:  Richard Frith-Macdonald <richard@brainstorm.co.uk>
5
5
   Created: October 1998
21
21
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
22
22
 
23
23
   <title>NSDistributedNotificationCenter class reference</title>
24
 
   $Date: 2002/03/10 08:08:11 $ $Revision: 1.21 $
 
24
   $Date: 2005/02/22 11:22:44 $ $Revision: 1.36 $
25
25
   */
26
26
 
27
 
#include        <config.h>
28
 
#include        <base/preface.h>
29
 
#include        <Foundation/NSObject.h>
30
 
#include        <Foundation/NSConnection.h>
31
 
#include        <Foundation/NSDistantObject.h>
32
 
#include        <Foundation/NSException.h>
33
 
#include        <Foundation/NSArchiver.h>
34
 
#include        <Foundation/NSNotification.h>
35
 
#include        <Foundation/NSDate.h>
36
 
#include        <Foundation/NSPathUtilities.h>
37
 
#include        <Foundation/NSRunLoop.h>
38
 
#include        <Foundation/NSTask.h>
39
 
#include        <Foundation/NSDistributedNotificationCenter.h>
40
 
#include        <Foundation/NSUserDefaults.h>
41
 
#include        <Foundation/NSHost.h>
 
27
#include        "config.h"
 
28
#include        "GNUstepBase/preface.h"
 
29
#include        "Foundation/NSObject.h"
 
30
#include        "Foundation/NSConnection.h"
 
31
#include        "Foundation/NSDistantObject.h"
 
32
#include        "Foundation/NSException.h"
 
33
#include        "Foundation/NSArchiver.h"
 
34
#include        "Foundation/NSNotification.h"
 
35
#include        "Foundation/NSDate.h"
 
36
#include        "Foundation/NSPathUtilities.h"
 
37
#include        "Foundation/NSRunLoop.h"
 
38
#include        "Foundation/NSTask.h"
 
39
#include        "Foundation/NSDistributedNotificationCenter.h"
 
40
#include        "Foundation/NSUserDefaults.h"
 
41
#include        "Foundation/NSHost.h"
 
42
#include        "Foundation/NSPortNameServer.h"
42
43
 
43
44
#include        "../Tools/gdnc.h"
44
45
 
45
 
/*
46
 
 *      Macros to build text to start name server and to give an error
47
 
 *      message about it - they include installation path information.
48
 
 */
49
 
#define MAKE_GDNC_CMD      [GSSystemRootDirectory() \
50
 
                              stringByAppendingPathComponent: @"Tools/gdnc"]
51
 
#define MAKE_GDNC_ERR      [NSString stringWithFormat: \
52
 
                                     @"check that %@/Tools/gdnc is running", \
53
 
                                     GSSystemRootDirectory()]
54
 
 
55
 
/*
56
 
 *      Global variables for distributed notification center types.
57
 
 */
58
 
NSString        *NSLocalNotificationCenterType =
59
 
                        @"NSLocalNotificationCenterType";
60
 
 
61
46
 
62
47
@interface      NSDistributedNotificationCenter (Private)
63
48
- (void) _connect;
69
54
                           to: (unsigned long)observer;
70
55
@end
71
56
 
 
57
/**
 
58
 * <p>The <code>NSDistributedNotificationCenter</code> provides a versatile yet
 
59
 * simple mechanism for objects in different processes to communicate
 
60
 * effectively while knowing very little about each others' internals.<br />
 
61
 * A distributed notification center acts much like a normal
 
62
 * notification center, but it handles notifications on a machine-wide
 
63
 * (or local network wide) basis rather than just notifications within
 
64
 * a single process.  Objects are able to register themselves as
 
65
 * observers for particular notification names and objects, and they
 
66
 * will then receive notifications (including optional user information
 
67
 * consisting of a dictionary of property-list objects) as they are posted.
 
68
 * </p>
 
69
 * <p>Since posting of distributed notifications involves inter-process
 
70
 * (and sometimes inter-host) communication, it is fundamentally slower
 
71
 * than normal notifications, and should be used relatively sparingly.
 
72
 * In order to help with this, the <code>NSDistributedNotificationCenter</code>
 
73
 * provides a notion of 'suspension', whereby a center can be suspended
 
74
 * causing notifications for observers in the process where the center
 
75
 * was suspended to cease receiving notifications.  Observers can
 
76
 * specify how notifications are to be handled in this case (queued
 
77
 * or discarded) and posters can specify that particular notifications
 
78
 * are to be delivered immediately irrespective of suspension.
 
79
 * </p>
 
80
 * <p>Distributed notifications are mediated by a server process which
 
81
 * handles all notifications for a particular center type.  In GNUstep
 
82
 * this process is the <code>gdnc</code> tool, and when started without special
 
83
 * options, a gdnc process acts as the local centre for the host it is
 
84
 * running on.  When started with the <code>GSNetwork</code> user default set
 
85
 * to YES, the <code>gdnc</code> tool acts as a local network wide server (you
 
86
 * should only run one copy of <code>gdnc</code> like this on your LAN).<br />
 
87
 * The <code>gdnc</code> process should be started at machine boot time, but
 
88
 * GNUstep will attempt to start it automatically if it can't find it.
 
89
 * </p>
 
90
 * <p>MacOS-X currently defines only a notification center for the
 
91
 * local host.  GNUstep also defines a local network center which can
 
92
 * be used from multiple hosts.  By default the system sends this to
 
93
 * any gdnc process it can find which is configured as a network-wide
 
94
 * server, but the <code>GDNCHost</code> user default may be used to specify a
 
95
 * particular host to be contacted ... this may be of use where you
 
96
 * wish to have logically separate clusters of machines on a shared LAN.
 
97
 * </p>
 
98
 */
72
99
@implementation NSDistributedNotificationCenter
73
100
 
74
 
static NSDistributedNotificationCenter  *defCenter = nil;
75
 
 
 
101
static NSDistributedNotificationCenter  *locCenter = nil;
 
102
static NSDistributedNotificationCenter  *netCenter = nil;
 
103
 
 
104
+ (id) allocWithZone: (NSZone*)z
 
105
{
 
106
  [NSException raise: NSInternalInconsistencyException
 
107
    format: @"Should not call +alloc for NSDistributedNotificationCenter"];
 
108
  return nil;
 
109
}
 
110
 
 
111
/**
 
112
 * Returns the default notification center ... a shared notification
 
113
 * center for the local host.  This is simply a convenience method
 
114
 * equivalent to calling +notificationCenterForType: with
 
115
 * <code>NSLocalNotificationCenterType</code> as its argument.
 
116
 */
76
117
+ (id) defaultCenter
77
118
{
78
119
  return [self notificationCenterForType: NSLocalNotificationCenterType];
79
120
}
80
121
 
 
122
/**
 
123
 * Returns a notification center of the specified type.<br />
 
124
 * The <code>NSLocalNotificationCenterType</code> provides a shared access to
 
125
 * a notificatiuon center used by processes on the local host.<br />
 
126
 * The <code>GSNetworkNotificationCenterType</code> provides a shared access to
 
127
 * a notificatiuon center used by processes on the local network.<br />
 
128
 * MacOS-X supports only <code>NSLocalNotificationCenterType</code>.
 
129
 */
81
130
+ (id) notificationCenterForType: (NSString*)type
82
131
{
83
 
  NSAssert([type isEqual: NSLocalNotificationCenterType],
84
 
        NSInvalidArgumentException);
85
 
  if (defCenter == nil)
86
 
    {
87
 
      [gnustep_global_lock lock];
88
 
        if (defCenter == nil)
89
 
          {
90
 
            NS_DURING
91
 
              {
92
 
                id      tmp;
93
 
 
94
 
                tmp = NSAllocateObject(self, 0, NSDefaultMallocZone());
95
 
                defCenter = (NSDistributedNotificationCenter*)[tmp init];
96
 
              }
97
 
            NS_HANDLER
98
 
              {
99
 
                [gnustep_global_lock unlock];
100
 
                [localException raise];
101
 
              }
102
 
            NS_ENDHANDLER
103
 
          }
104
 
      [gnustep_global_lock unlock];
105
 
    }
106
 
  return defCenter;
 
132
  if ([type isEqual: NSLocalNotificationCenterType] == YES)
 
133
    {
 
134
      if (locCenter == nil)
 
135
        {
 
136
          [gnustep_global_lock lock];
 
137
            if (locCenter == nil)
 
138
              {
 
139
                NS_DURING
 
140
                  {
 
141
                    NSDistributedNotificationCenter     *tmp;
 
142
 
 
143
                    tmp = (NSDistributedNotificationCenter*)
 
144
                      NSAllocateObject(self, 0, NSDefaultMallocZone());
 
145
                    tmp->_centerLock = [NSRecursiveLock new];
 
146
                    tmp->_type = RETAIN(NSLocalNotificationCenterType);
 
147
                    locCenter = tmp;
 
148
                  }
 
149
                NS_HANDLER
 
150
                  {
 
151
                    [gnustep_global_lock unlock];
 
152
                    [localException raise];
 
153
                  }
 
154
                NS_ENDHANDLER
 
155
              }
 
156
          [gnustep_global_lock unlock];
 
157
        }
 
158
      return locCenter;
 
159
    }
 
160
  else if ([type isEqual: GSNetworkNotificationCenterType] == YES)
 
161
    {
 
162
      if (netCenter == nil)
 
163
        {
 
164
          [gnustep_global_lock lock];
 
165
            if (netCenter == nil)
 
166
              {
 
167
                NS_DURING
 
168
                  {
 
169
                    NSDistributedNotificationCenter     *tmp;
 
170
 
 
171
                    tmp = (NSDistributedNotificationCenter*)
 
172
                      NSAllocateObject(self, 0, NSDefaultMallocZone());
 
173
                    tmp->_centerLock = [NSRecursiveLock new];
 
174
                    tmp->_type = RETAIN(GSNetworkNotificationCenterType);
 
175
                    netCenter = tmp;
 
176
                  }
 
177
                NS_HANDLER
 
178
                  {
 
179
                    [gnustep_global_lock unlock];
 
180
                    [localException raise];
 
181
                  }
 
182
                NS_ENDHANDLER
 
183
              }
 
184
          [gnustep_global_lock unlock];
 
185
        }
 
186
      return netCenter;
 
187
    }
 
188
  else
 
189
    {
 
190
      [NSException raise: NSInvalidArgumentException
 
191
                  format: @"Unknown center type (%@)", type];
 
192
      return nil;       /* NOT REACHED */
 
193
    }
107
194
}
108
195
 
109
196
- (void) dealloc
113
200
      [_remote unregisterClient: (id<GDNCClient>)self];
114
201
    }
115
202
  RELEASE(_remote);
116
 
  [super dealloc];
 
203
  RELEASE(_type);
 
204
  NSDeallocateObject(self);
117
205
}
118
206
 
 
207
/**
 
208
 * Should not be used.
 
209
 */
119
210
- (id) init
120
211
{
121
 
  NSAssert(_centerLock == nil, NSInternalInconsistencyException);
122
 
  _centerLock = [NSRecursiveLock new];
123
 
  return self;
 
212
  RELEASE(self);
 
213
  [NSException raise: NSInternalInconsistencyException
 
214
    format: @"Should not call -init for NSDistributedNotificationCenter"];
 
215
  return nil;
124
216
}
125
217
 
 
218
/**
 
219
 * Adds an observer to the receiver.  Calls
 
220
 * -addObserver:selector:name:object:suspensionBehavior: with
 
221
 * <code>NSNotificationSuspensionBehaviorCoalesce</code>.
 
222
 */
126
223
- (void) addObserver: (id)anObserver
127
224
            selector: (SEL)aSelector
128
225
                name: (NSString*)notificationName
135
232
 suspensionBehavior: NSNotificationSuspensionBehaviorCoalesce];
136
233
}
137
234
 
 
235
/**
 
236
 * Adds an observer to the receiver.<br />
 
237
 * When a notification matching notificationName and anObject is
 
238
 * sent to the center, the object anObserver is sent the message
 
239
 * aSelector with the notification info dictionary as its argument.<br />
 
240
 * The suspensionBehavior governs how the center deals with notifications
 
241
 * when the process to which the notification should be delivered is
 
242
 * suspended:
 
243
 * <deflist>
 
244
 *  <term><code>NSNotificationSuspensionBehaviorDrop</code></term>
 
245
 *  <desc>
 
246
 *    Discards the notification if the observing process is suspended.
 
247
 *  </desc>
 
248
 *  <term><code>NSNotificationSuspensionBehaviorCoalesce</code></term>
 
249
 *  <desc>
 
250
 *    Discards previously queued notifications when the observing process
 
251
 *    is suspended, leaving only the last notification posted in the queue.
 
252
 *    Delivers this single notification when the process becomes unsuspended.
 
253
 *  </desc>
 
254
 *  <term><code>NSNotificationSuspensionBehaviorHold</code></term>
 
255
 *  <desc>
 
256
 *    Queues notifications when the observing process is suspended,
 
257
 *    delivering all the queued notifications when the process becomes
 
258
 *    unsuspended again.
 
259
 *  </desc>
 
260
 *  <term><code>NSNotificationSuspensionBehaviorDeliverImmediately</code></term>
 
261
 *  <desc>
 
262
 *    Deliver the notification immediately, even if the destination
 
263
 *    process is suspended.
 
264
 *  </desc>
 
265
 * </deflist>
 
266
 */
138
267
- (void) addObserver: (id)anObserver
139
268
            selector: (SEL)aSelector
140
269
                name: (NSString*)notificationName
149
278
  if (aSelector == 0)
150
279
    {
151
280
      [NSException raise: NSInvalidArgumentException
152
 
                  format: @"nul selector"];
 
281
                  format: @"null selector"];
153
282
    }
154
 
  if (notificationName != nil &&
155
 
        [notificationName isKindOfClass: [NSString class]] == NO)
 
283
  if (notificationName != nil
 
284
    && [notificationName isKindOfClass: [NSString class]] == NO)
156
285
    {
157
286
      [NSException raise: NSInvalidArgumentException
158
287
                  format: @"invalid notification name"];
188
317
  [_centerLock unlock];
189
318
}
190
319
 
 
320
/**
 
321
 * Posts the notification to the center using
 
322
 * postNotificationName:object:userInfo:deliverImmediately: with the
 
323
 * delivery flag set to NO.
 
324
 */
191
325
- (void) postNotification: (NSNotification*)notification
192
326
{
193
327
  [self postNotificationName: [notification name]
196
330
          deliverImmediately: NO];
197
331
}
198
332
 
 
333
/**
 
334
 * Posts the notificationName and anObject to the center using
 
335
 * postNotificationName:object:userInfo:deliverImmediately: with the
 
336
 * user info set to nil and the delivery flag set to NO.
 
337
 */
199
338
- (void) postNotificationName: (NSString*)notificationName
200
339
                       object: (NSString*)anObject
201
340
{
205
344
          deliverImmediately: NO];
206
345
}
207
346
 
 
347
/**
 
348
 * Posts the notificationName, anObject and userInfo to the center using
 
349
 * postNotificationName:object:userInfo:deliverImmediately: with the
 
350
 * delivery flag set to NO.
 
351
 */
208
352
- (void) postNotificationName: (NSString*)notificationName
209
353
                       object: (NSString*)anObject
210
354
                     userInfo: (NSDictionary*)userInfo
215
359
          deliverImmediately: NO];
216
360
}
217
361
 
 
362
/**
 
363
 * The primitive notification posting method ...<br />
 
364
 * The userInfo dictionary may contain only property-list objects.<br />
 
365
 * The deliverImmediately flag specifies whether the suspension
 
366
 * state of the receiving process is to be ignored.
 
367
 */
218
368
- (void) postNotificationName: (NSString*)notificationName
219
369
                       object: (NSString*)anObject
220
370
                     userInfo: (NSDictionary*)userInfo
221
371
           deliverImmediately: (BOOL)deliverImmediately
222
372
{
223
 
  if (notificationName == nil ||
224
 
        [notificationName isKindOfClass: [NSString class]] == NO)
 
373
  if (notificationName == nil
 
374
    || [notificationName isKindOfClass: [NSString class]] == NO)
225
375
    {
226
376
      [NSException raise: NSInvalidArgumentException
227
377
                  format: @"invalid notification name"];
254
404
  [_centerLock unlock];
255
405
}
256
406
 
 
407
/**
 
408
 * Removes the observer from the center.
 
409
 */
257
410
- (void) removeObserver: (id)anObserver
258
411
                   name: (NSString*)notificationName
259
412
                 object: (NSString*)anObject
260
413
{
261
 
  if (notificationName != nil &&
262
 
        [notificationName isKindOfClass: [NSString class]] == NO)
 
414
  if (notificationName != nil
 
415
    && [notificationName isKindOfClass: [NSString class]] == NO)
263
416
    {
264
417
      [NSException raise: NSInvalidArgumentException
265
418
                  format: @"invalid notification name"];
288
441
  [_centerLock unlock];
289
442
}
290
443
 
 
444
/**
 
445
 * Sets the suspension state of the receiver ... if the receiver is
 
446
 * suspended, it won't handle notification until it is unsuspended
 
447
 * again, unless the notifications are posted to be delivered
 
448
 * immediately.
 
449
 */
291
450
- (void) setSuspended: (BOOL)flag
292
451
{
293
452
  [_centerLock lock];
306
465
  [_centerLock unlock];
307
466
}
308
467
 
 
468
/**
 
469
 * Returns the current suspension state of the receiver.
 
470
 */
309
471
- (BOOL) suspended
310
472
{
311
473
  return _suspended;
313
475
 
314
476
@end
315
477
 
 
478
/*
 
479
 * The following dummy class is here solely as a workaround for pre 3.3
 
480
 * versions of gcc where protocols didn't work properly unless implemented
 
481
 * in the source where the '@protocol()' directive is used.
 
482
 */
 
483
@interface NSDistributedNotificationCenterDummy : NSObject <GDNCProtocol>
 
484
- (void) addObserver: (unsigned long)anObserver
 
485
            selector: (NSString*)aSelector
 
486
                name: (NSString*)notificationname
 
487
              object: (NSString*)anObject
 
488
  suspensionBehavior: (NSNotificationSuspensionBehavior)suspensionBehavior
 
489
                 for: (id<GDNCClient>)client;
 
490
- (oneway void) postNotificationName: (NSString*)notificationName
 
491
                              object: (NSString*)anObject
 
492
                            userInfo: (NSData*)d
 
493
                  deliverImmediately: (BOOL)deliverImmediately
 
494
                                 for: (id<GDNCClient>)client;
 
495
- (void) registerClient: (id<GDNCClient>)client;
 
496
- (void) removeObserver: (unsigned long)anObserver
 
497
                   name: (NSString*)notificationname
 
498
                 object: (NSString*)anObject
 
499
                    for: (id<GDNCClient>)client;
 
500
- (void) setSuspended: (BOOL)flag
 
501
                  for: (id<GDNCClient>)client;
 
502
- (void) unregisterClient: (id<GDNCClient>)client;
 
503
@end
 
504
 
 
505
@implementation NSDistributedNotificationCenterDummy
 
506
- (void) addObserver: (unsigned long)anObserver
 
507
            selector: (NSString*)aSelector
 
508
                name: (NSString*)notificationname
 
509
              object: (NSString*)anObject
 
510
  suspensionBehavior: (NSNotificationSuspensionBehavior)suspensionBehavior
 
511
                 for: (id<GDNCClient>)client
 
512
{
 
513
}
 
514
- (oneway void) postNotificationName: (NSString*)notificationName
 
515
                              object: (NSString*)anObject
 
516
                            userInfo: (NSData*)d
 
517
                  deliverImmediately: (BOOL)deliverImmediately
 
518
                                 for: (id<GDNCClient>)client
 
519
{
 
520
}
 
521
- (void) registerClient: (id<GDNCClient>)client
 
522
{
 
523
}
 
524
- (void) removeObserver: (unsigned long)anObserver
 
525
                   name: (NSString*)notificationname
 
526
                 object: (NSString*)anObject
 
527
                    for: (id<GDNCClient>)client
 
528
{
 
529
}
 
530
- (void) setSuspended: (BOOL)flag
 
531
                  for: (id<GDNCClient>)client
 
532
{
 
533
}
 
534
- (void) unregisterClient: (id<GDNCClient>)client
 
535
{
 
536
}
 
537
@end
 
538
 
316
539
@implementation NSDistributedNotificationCenter (Private)
317
540
 
 
541
/**
 
542
 * Establish a connection to the server.  This method should only be called
 
543
 * when protected by the center's lock, so that it is thread-safe.
 
544
 */
318
545
- (void) _connect
319
546
{
320
547
  if (_remote == nil)
321
548
    {
322
 
      NSString  *host;
323
 
      NSString  *description;
324
 
 
325
 
      /*
326
 
       *        Connect to the NSDistributedNotificationCenter for this host.
327
 
       */
328
 
      host = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
329
 
      if (host == nil)
330
 
        {
331
 
          host = @"";
332
 
        }
333
 
      else
334
 
        {
335
 
          NSHost        *h;
336
 
 
 
549
      NSString  *host = nil;
 
550
      NSString  *service = nil;
 
551
      NSString  *description = nil;
 
552
 
 
553
      if (_type == NSLocalNotificationCenterType)
 
554
        {
337
555
          /*
338
 
           * If we have a host specified, but it is the current host,
339
 
           * we do not need to ask for a host by name (nameserver lookup
340
 
           * can be faster) and the empty host name can be used to
341
 
           * indicate that we may start a gdnc server locally.
 
556
           * Connect to the NSDistributedNotificationCenter for this host.
342
557
           */
343
 
          h = [NSHost hostWithName: host];
344
 
          if (h == nil)
345
 
            {
346
 
              NSLog(@"Unknown -NSHost '%@' ignored", host);
347
 
              host = @"";
348
 
            }
349
 
          else if ([h isEqual: [NSHost currentHost]] == YES)
350
 
            {
 
558
          host = [[NSUserDefaults standardUserDefaults]
 
559
            stringForKey: @"NSHost"];
 
560
          if (host == nil)
 
561
            {
 
562
              //host = @"localhost";
351
563
              host = @"";
352
564
            }
353
565
          else
354
566
            {
355
 
              host = [h name];
356
 
            }
357
 
        }
 
567
              NSHost    *h;
358
568
 
359
 
      if ([host length] == 0)
360
 
        {
361
 
          description = @"local host";
 
569
              /*
 
570
               * If we have a host specified, but it is the current host,
 
571
               * we do not need to ask for a host by name (nameserver lookup
 
572
               * can be faster) and the empty host name can be used to
 
573
               * indicate that we may start a <code>gdnc</code> server locally.
 
574
               */
 
575
              h = [NSHost hostWithName: host];
 
576
              if (h == nil)
 
577
                {
 
578
                  NSLog(@"Unknown -NSHost '%@' ignored", host);
 
579
                  host = @"";
 
580
                }
 
581
              else if ([h isEqual: [NSHost currentHost]] == YES)
 
582
                {
 
583
                  host = @"";
 
584
                }
 
585
              else
 
586
                {
 
587
                  host = [h name];
 
588
                }
 
589
            }
 
590
          if ([host length] == 0
 
591
            || [host isEqualToString: @"localhost"] == YES
 
592
            || [host isEqualToString: @"127.0.0.1"] == YES)
 
593
            {
 
594
              description = @"local host";
 
595
            }
 
596
          else
 
597
            {
 
598
              description = host;
 
599
            }
 
600
          service = GDNC_SERVICE;
362
601
        }
363
 
      else
364
 
        {
 
602
      else if (_type == GSNetworkNotificationCenterType)
 
603
        {
 
604
          host = [[NSUserDefaults standardUserDefaults]
 
605
            stringForKey: @"GDNCHost"];
365
606
          description = host;
366
 
        }
367
 
 
368
 
      _remote = RETAIN([NSConnection rootProxyForConnectionWithRegisteredName:
369
 
        GDNC_SERVICE host: host]);
370
 
      if (_remote == nil && [host isEqual: @""] == NO)
371
 
        {
372
 
          _remote = [NSConnection rootProxyForConnectionWithRegisteredName:
373
 
            [GDNC_SERVICE stringByAppendingFormat: @"-%@", host] host: @"*"];
 
607
          if (host == nil)
 
608
            {
 
609
              host = @"*";
 
610
              description = @"network host";
 
611
            }
 
612
          service = GDNC_NETWORK;
 
613
        }
 
614
      else
 
615
        {
 
616
          [NSException raise: NSInternalInconsistencyException
 
617
                      format: @"Unknown center type - %@", _type];
 
618
        }
 
619
 
 
620
      if ([host isEqualToString: @"*"] == YES)
 
621
        {
 
622
          _remote = [NSConnection rootProxyForConnectionWithRegisteredName:
 
623
            service host: host
 
624
            usingNameServer: [NSSocketPortNameServer sharedInstance]];
 
625
        }
 
626
      else
 
627
        {
 
628
          _remote = [NSConnection rootProxyForConnectionWithRegisteredName:
 
629
            service host: host];
 
630
        }
 
631
      RETAIN(_remote);
 
632
 
 
633
      if (_type == NSLocalNotificationCenterType
 
634
        && _remote == nil && [host isEqual: @""] == NO)
 
635
        {
 
636
          _remote = [NSConnection rootProxyForConnectionWithRegisteredName:
 
637
            [service stringByAppendingFormat: @"-%@", host] host: @"*"];
374
638
          RETAIN(_remote);
375
639
        }
376
640
 
380
644
          Protocol      *p = @protocol(GDNCProtocol);
381
645
 
382
646
          [_remote setProtocolForProxy: p];
 
647
        
 
648
          /*
 
649
           * Ensure that this center can be used safely from different
 
650
           * threads.
 
651
           */
 
652
          [c enableMultipleThreads];
383
653
 
384
654
          /*
385
655
           *    Ask to be told if the connection goes away.
393
663
        }
394
664
      else
395
665
        {
396
 
          static BOOL recursion = NO;
 
666
          static BOOL           recursion = NO;
 
667
          static NSString       *cmd = nil;
 
668
          static NSArray        *args = nil;
397
669
 
398
670
          if (recursion == NO)
399
671
            {
400
 
              static NSString   *cmd = nil;
401
 
              static NSArray    *args = nil;
402
 
 
403
 
              NSLog(@"\nI couldn't contact the notification server for %@ -\n"
404
 
@"so I'm attempting to to start one - which will take a few seconds.\n"
405
 
@"It is recommended that you start the notification server (gdnc) either at\n"
406
 
@"login or (better) when your computer is started up.\n", description);
407
 
 
408
672
              if (cmd == nil)
409
673
                {
410
 
#if 1
411
674
                  cmd = RETAIN([[NSSearchPathForDirectoriesInDomains(
412
675
                    GSToolsDirectory, NSSystemDomainMask, YES) objectAtIndex: 0]
413
676
                    stringByAppendingPathComponent: @"gdnc"]);
414
 
#else
415
 
                  cmd = MAKE_GDNC_CMD;
416
 
#endif
417
 
                  if ([host length] > 0)
418
 
                    {
419
 
                      args = [[NSArray alloc] initWithObjects:
420
 
                        @"-NSHost", host, nil];
421
 
                    }
 
677
                }
 
678
            }
 
679
          if (recursion == NO && cmd != nil)
 
680
            {
 
681
              NSLog(@"\nI couldn't contact the notification server for %@ -\n"
 
682
@"so I'm attempting to to start one - which will take a few seconds.\n"
 
683
@"Trying to launch gdnc from %@ or a machine/operating-system subdirectory.\n"
 
684
@"It is recommended that you start the notification server (gdnc) either at\n"
 
685
@"login or (better) when your computer is started up.\n", description,
 
686
[cmd stringByDeletingLastPathComponent]);
 
687
 
 
688
              if (_type == GSNetworkNotificationCenterType)
 
689
                {
 
690
                  args = [[NSArray alloc] initWithObjects:
 
691
                    @"-GSNetwork", @"YES", nil];
 
692
                }
 
693
              else if ([host length] > 0)
 
694
                {
 
695
                  args = [[NSArray alloc] initWithObjects:
 
696
                    @"-NSHost", host, nil];
422
697
                }
423
698
 
424
699
              [NSTask launchedTaskWithLaunchPath: cmd arguments: args];
432
707
              recursion = NO;
433
708
            }
434
709
          else
435
 
            { 
 
710
            {
436
711
              recursion = NO;
437
712
              [NSException raise: NSInternalInconsistencyException
438
 
                          format: @"unable to contact GDNC server - %@",
439
 
                           MAKE_GDNC_ERR];
 
713
                          format: @"unable to contact GDNC server -\n"
 
714
                @"please check that the gdnc process is running."];
440
715
            }
441
716
        }
442
717
    }