Fixed lazy loading of plug-ins.
authorPeter Hosey <hg@boredzo.org>
Sat Oct 03 23:26:34 2009 -0700 (2009-10-03)
changeset 44899c0b9f927d0e
parent 4488 8b26f543636c
child 4490 4e571142d4ce
Fixed lazy loading of plug-ins.
Core/Source/GrowlApplicationTicket.m
Core/Source/GrowlNotificationTicket.m
Core/Source/GrowlPluginController.h
Core/Source/GrowlPluginController.m
     1.1 --- a/Core/Source/GrowlApplicationTicket.m	Sat Oct 03 19:48:03 2009 -0700
     1.2 +++ b/Core/Source/GrowlApplicationTicket.m	Sat Oct 03 23:26:34 2009 -0700
     1.3 @@ -447,7 +447,7 @@
     1.4  
     1.5  - (GrowlDisplayPlugin *) displayPlugin {
     1.6  	if (!displayPlugin && displayPluginName)
     1.7 -		displayPlugin = (GrowlDisplayPlugin *)[[[GrowlPluginController sharedController] displayPluginDictionaryWithName:displayPluginName author:nil version:nil type:nil] pluginInstance];
     1.8 +		displayPlugin = (GrowlDisplayPlugin *)[[GrowlPluginController sharedController] displayPluginInstanceWithName:displayPluginName author:nil version:nil type:nil];
     1.9  	return displayPlugin;
    1.10  }
    1.11  
     2.1 --- a/Core/Source/GrowlNotificationTicket.m	Sat Oct 03 19:48:03 2009 -0700
     2.2 +++ b/Core/Source/GrowlNotificationTicket.m	Sat Oct 03 23:26:34 2009 -0700
     2.3 @@ -210,7 +210,7 @@
     2.4  
     2.5  - (GrowlDisplayPlugin *) displayPlugin {
     2.6  	if (!displayPlugin && displayPluginName)
     2.7 -		displayPlugin = (GrowlDisplayPlugin *)[[[GrowlPluginController sharedController] displayPluginDictionaryWithName:displayPluginName author:nil version:nil type:nil] pluginInstance];
     2.8 +		displayPlugin = (GrowlDisplayPlugin *)[[GrowlPluginController sharedController] displayPluginInstanceWithName:displayPluginName author:nil version:nil type:nil];
     2.9  	return displayPlugin;
    2.10  }
    2.11  
     3.1 --- a/Core/Source/GrowlPluginController.h	Sat Oct 03 19:48:03 2009 -0700
     3.2 +++ b/Core/Source/GrowlPluginController.h	Sat Oct 03 23:26:34 2009 -0700
     3.3 @@ -130,6 +130,9 @@
     3.4  @interface GrowlPluginController : GrowlAbstractSingletonObject <GrowlPluginHandler> {
     3.5  	//Keys: plug-in IDs; values: plug-in description dictionaries.
     3.6  	NSMutableDictionary       *pluginsByIdentifier;
     3.7 +	//Keys: bundle IDs; values: plug-in description dictionaries.
     3.8 +	//We use this to avoid attempting to load two bundles with the same bundle ID.
     3.9 +	NSMutableDictionary       *pluginsByBundleIdentifier;
    3.10  	//Keys: plug-in paths/bundles/instances; values: plug-in identifiers.
    3.11  	NSMutableDictionary       *pluginIdentifiersByPath;
    3.12  	NSMapTable *pluginIdentifiersByBundle;
    3.13 @@ -143,12 +146,6 @@
    3.14  	//Used for triple-disambiguated names (e.g. 'Smoke (by Matthew Walton, filename Smoke.growlView)'). Multiple equal names become '...', '... 2', '... 3', etc.
    3.15  	NSCountedSet          *pluginHumanReadableNames;
    3.16  
    3.17 -	/* A set of the identifiers of all loaded bundles to easily prevent loading the same bundle twice.
    3.18 -	 * This might be duplicative with one of the dictionaries above.  I can't tell, but we need to avoid
    3.19 -	 * duplication of bundle loading. -eds
    3.20 -	 */
    3.21 -	NSMutableSet	*loadedBundleIdentifiers;
    3.22 -	
    3.23  	NSMutableSet *bundlesToLazilyInstantiateAnInstanceFrom;
    3.24  	//GrowlDisplayPlugin instances that have been added as display plugins.
    3.25  	//These two arrays are parallel.
     4.1 --- a/Core/Source/GrowlPluginController.m	Sat Oct 03 19:48:03 2009 -0700
     4.2 +++ b/Core/Source/GrowlPluginController.m	Sat Oct 03 23:26:34 2009 -0700
     4.3 @@ -88,6 +88,7 @@
     4.4  		bundlesToLazilyInstantiateAnInstanceFrom = [[NSMutableSet alloc] init];
     4.5  
     4.6  		pluginsByIdentifier         = [[NSMutableDictionary alloc] init];
     4.7 +		pluginsByBundleIdentifier   = [[NSMutableDictionary alloc] init];
     4.8  		pluginIdentifiersByPath     = [[NSMutableDictionary alloc] init];
     4.9  		pluginIdentifiersByBundle   = [[NSMapTable mapTableWithStrongToStrongObjects] retain];
    4.10  		pluginIdentifiersByInstance = [[NSMapTable mapTableWithStrongToStrongObjects] retain];
    4.11 @@ -99,8 +100,7 @@
    4.12  		pluginsByType     = [[NSMutableDictionary alloc] init];
    4.13  		pluginHumanReadableNames = [[NSCountedSet alloc] init];
    4.14  
    4.15 -		loadedBundleIdentifiers = [[NSMutableSet alloc] init];
    4.16 -		
    4.17 +
    4.18  		allPluginHandlers = [[NSMutableArray alloc] init];
    4.19  		pluginHandlers  = [[NSMutableDictionary alloc] init];
    4.20  		handlersForPlugins = [[NSMapTable mapTableWithStrongToStrongObjects] retain];
    4.21 @@ -145,6 +145,7 @@
    4.22  
    4.23  - (void) destroy {
    4.24  	[pluginsByIdentifier         release];
    4.25 +	[pluginsByBundleIdentifier   release];
    4.26  	[pluginIdentifiersByPath     release];
    4.27  	[pluginIdentifiersByBundle   release];
    4.28  	[pluginIdentifiersByInstance release];
    4.29 @@ -156,8 +157,6 @@
    4.30  	[pluginsByType     release];
    4.31  	[pluginHumanReadableNames release];
    4.32  
    4.33 -	[loadedBundleIdentifiers release];
    4.34 -
    4.35  	[bundlesToLazilyInstantiateAnInstanceFrom release];
    4.36  	[displayPlugins release];
    4.37  	[disabledPlugins release];
    4.38 @@ -329,10 +328,13 @@
    4.39  
    4.40  //private method.
    4.41  - (NSDictionary *) addPluginInstance:(GrowlPlugin *)plugin fromPath:(NSString *)path bundle:(NSBundle *)bundle {
    4.42 -	//If we're passed a bundle, refuse to load it if we've already loaded a bundle with the same identifier, instead returning early.
    4.43 -	NSString *bundleIdentifier = (bundle ? [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey] : nil);
    4.44 -	if (bundleIdentifier && [loadedBundleIdentifiers containsObject:bundleIdentifier]) {
    4.45 -		return nil;
    4.46 +	//If we're passed a bundle, refuse to load it if we've already loaded a different bundle with the same identifier, instead returning whatever dictionary we already have.
    4.47 +	NSMutableDictionary *pluginDict = nil;
    4.48 +	NSString *bundleIdentifier = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
    4.49 +	if (bundleIdentifier) {
    4.50 +		pluginDict = [pluginsByBundleIdentifier objectForKey:bundleIdentifier];
    4.51 +		if (pluginDict && (bundle != [pluginDict pluginBundle]))
    4.52 +			return pluginDict;
    4.53  	}
    4.54  	
    4.55  	//Look up the identifier for the plugin. We try to look up the identifier by the instance, by the bundle; and by the pathname, in that order.
    4.56 @@ -347,7 +349,7 @@
    4.57  	/* If we have an identifier, look up the plug-in dictionary.
    4.58  	 * If we have a plug-in dictionary but no instance (the identifier was retrieved by bundle or by path), attempt to retrieve the instance from the dictionary.
    4.59  	 */
    4.60 -	NSMutableDictionary *pluginDict = identifier ? [pluginsByIdentifier objectForKey:identifier] : nil;
    4.61 +	pluginDict = identifier ? [pluginsByIdentifier objectForKey:identifier] : nil;
    4.62  	if (pluginDict && !plugin)
    4.63  		plugin = [pluginDict pluginInstance];
    4.64  
    4.65 @@ -401,17 +403,6 @@
    4.66  		}
    4.67  	}
    4.68  
    4.69 -	if (!plugin && bundle) {
    4.70 -		//*Still* no plug-in! Again we check whether it's queued for instantiation (bug?).
    4.71 -		if (![bundlesToLazilyInstantiateAnInstanceFrom containsObject:bundle])
    4.72 -			[bundlesToLazilyInstantiateAnInstanceFrom addObject:bundle];
    4.73 -		else {
    4.74 -			//Apparently it is. Instantiate it, but don't stash the plug-in instance in the plug-in dictionary (why not?).
    4.75 -			plugin = [[[[bundle principalClass] alloc] init] autorelease];
    4.76 -			[bundlesToLazilyInstantiateAnInstanceFrom removeObject:bundle];
    4.77 -		}
    4.78 -	}
    4.79 -
    4.80  	/*If we don't actually have a plug-in dictionary, create it.
    4.81  	 *Elements of a plug-in dictionary:
    4.82  	 *	Plug-in name
    4.83 @@ -525,7 +516,7 @@
    4.84  
    4.85  	//Store the bundle identifier so we know we've loaded it.
    4.86  	if (bundleIdentifier) {
    4.87 -		[loadedBundleIdentifiers addObject:bundleIdentifier];
    4.88 +		[pluginsByBundleIdentifier setObject:pluginDict forKey:bundleIdentifier];
    4.89  	}
    4.90  
    4.91  	return pluginDict;
    4.92 @@ -677,9 +668,8 @@
    4.93  	else {
    4.94  		NSBundle *bundle = [pluginDict pluginBundle];
    4.95  		NSAssert1(bundle, @"no instance or bundle in plug-in dictionary! description of dictionary follows\n%@", pluginDict);
    4.96 -		Class principalClass = [bundle principalClass];
    4.97 -		NSAssert1(bundle, @"bundle in plug-in dictionary has no principal class! description of dictionary follows\n%@", pluginDict);
    4.98 -		return [principalClass isSubclassOfClass:[GrowlDisplayPlugin class]];
    4.99 +		NSString *ext = [[bundle bundlePath] pathExtension];
   4.100 +		return [ext isEqualToString:GROWL_VIEW_EXTENSION] || [ext isEqualToString:GROWL_STYLE_EXTENSION];
   4.101  	}
   4.102  }
   4.103