| Index | Submit class | Submit snippet | Submission feed | List |

BSPluginLoader

Language: Objective-C, Author: Karsten
License: Public domain

BSPluginLoader is a loadable bundle that allows applications to easily load plugins. The plugins can be installed in any applications support folder or in the application's bundle itself.

BSPluginLoader source preview

//
//  BSPluginLoader.m
//  BSPluginLoader
//
//  Created by Karsten Kusche on 30.03.07.
//

/*
 todos:
 
 - move stuff to instance side
 - make loader more customizable (execute method with object)
 
 */

#import "BSPluginLoader.h"


@implementation BSPluginLoader

- (NSArray*)domainPathes
{
  // domain pathes are used as a basis for searching for plugins.
  // appending subfolders like 'plugins' to them should list all folders that are used to store plugins.
  static NSMutableArray* domains;
  if (domains)
  {
    return domains;
  }
  domains = [[NSMutableArray alloc] init];    

  //get the processes name, it's used as subfolder in the app-support folders
  NSString* appName = [[NSProcessInfo processInfo] processName];
  
  NSEnumerator* basicDomains = [[NSArray arrayWithObjects: 
    @"~/Library/Application Support/", 
    @"/Library/Application Support/",
    @"/System/Library/Application Support/",
    nil] objectEnumerator]; 
  NSString* domain;
  while (domain = [basicDomains nextObject])
  {
    [domains addObject:[[domain stringByExpandingTildeInPath] stringByAppendingPathComponent:appName]];
  }
  
  // finally add the bundle's contents folder
  [domains addObject:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents"]];
  return domains;
}

- (void)initBundle:(NSBundle*)bundle
{
  Class class = [bundle principalClass];
//  NSLog(@"principal class for bundle:%@ is: %@",[[bundle bundlePath] lastPathComponent],[class description]);
  if (class)
  {
    if (selector)
    {
      if (sender)
      {
        [sender performSelector:selector withObject: class];
      }
    }
  }
}

- (int)loadPluginsInDomain:(NSString*)domain atPath:(NSString*)aPath withExtensions: (NSArray*)extensions
{
  int bundleCount = 0;
  NSString* pluginFolder = [[domain stringByExpandingTildeInPath] stringByAppendingPathComponent:aPath];
  NSArray* pluginFiles = [[NSFileManager defaultManager] directoryContentsAtPath:pluginFolder];
  
  // if folder doesn't exist, return
  if (pluginFiles == nil) return 0;
  
  NSEnumerator* plugins = [pluginFiles objectEnumerator];
  NSString* plugin;
  while (plugin = [plugins nextObject])
  {
    // check if plugin extension is exqual to the required extension
    if ([extensions containsObject:[plugin pathExtension]])
    {
      // load bundle
      NSBundle* pluginBundle = [NSBundle bundleWithPath:[pluginFolder stringByAppendingPathComponent:plugin]];
      if ([pluginBundle load])
      {
        //load was successful, increment the counter and init the bundle
        bundleCount ++;
        [self initBundle: pluginBundle];
      }
    }
  }
  return bundleCount;
}

- (int)loadPluginsAtPath:(NSString*)aPath withExtension: (NSString*)extension
{
  return [self loadPluginsAtPath:aPath withExtensions:[NSArray arrayWithObject:extension]];
}

- (int)loadPluginsAtPath:(NSString*)aPath withExtensions: (NSArray*)extensions
{
  int bundleCount = 0;
  
  NSEnumerator* domains = [[self domainPathes] objectEnumerator];
  NSString* domain;
  while (domain = [domains nextObject])
  {
    bundleCount += [self loadPluginsInDomain: domain atPath: aPath withExtensions: extensions];
  }
  // return how many bundles loaded successfully
  return bundleCount;
}

+ (int)loadPluginsAtPath:(NSString*)aPath withExtension: (NSString*)extension
{
  return [self loadPluginsAtPath:aPath withExtensions:[NSArray arrayWithObject:extension]];
}

+ (int)loadPluginsAtPath:(NSString*)aPath withExtensions: (NSArray*)extensions
{
  BSPluginLoader* loader = [[self alloc] init];
  int bundleCount = [loader loadPluginsAtPath:aPath withExtensions:extensions];
  [loader release];

  return bundleCount;
}

- (id) init {
  self = [super init];
  if (self != nil) {
    selector = nil;
    sender = nil;
  }
  return self;
}


- (void)setSelector:(SEL)newSelector
{
  selector = newSelector;
}

- (void)setSender:(id)newsender
{
  [sender release];
  sender = [newsender retain];
}

- (void) dealloc {
  [sender release];
  [super dealloc];
}

+ (id)loaderForSender:(id)sender notifyingWith:(SEL)selector
{
  BSPluginLoader* loader = [[self alloc] init];
  
  [loader setSender:sender];
  [loader setSelector:selector];
  
  return loader;
}
@end

BSPluginLoader header preview

//
//  BSPluginLoader.h
//  BSPluginLoader
//
//  Created by Karsten Kusche on 30.03.07.
//

#import <Cocoa/Cocoa.h>

/*
 
 BSPluginLoader will load all plugins into your application that have a given extension and are located in a given subpath.
 it will search all domains (~/Library/Application Support /Library/Application Support /System/Library/Application Support) 
 as well as the application-bundle's contents folder.
 
 load the bundle by hand when your application launches and benefit of a simplified plugin loading mechanism.
 
 */

@interface BSPluginLoader : NSObject {
  SEL selector; // selector...has to accept the class that was loaded as argument
  id sender; // target that receives this selector
}


// create a new loader with sender and action
+ (id)loaderForSender:(id)sender notifyingWith:(SEL)selector;

// load plugins at a relative path (@"plugins" for example) and with a given extension, or extensions
+ (int)loadPluginsAtPath:(NSString*)aPath withExtension: (NSString*)extension;
+ (int)loadPluginsAtPath:(NSString*)aPath withExtensions: (NSArray*)extensions;

// same as the class methods, but notifying the target with the selector specified in the factory method
- (int)loadPluginsAtPath:(NSString*)aPath withExtension: (NSString*)extension;
- (int)loadPluginsAtPath:(NSString*)aPath withExtensions: (NSArray*)extensions;

// set the instance variables
- (void)setSelector:(SEL)newSelector;
- (void)setSender:(id)newSender;

@end
Download Archive

Compatible with:


Comments

Jean-Daniel Dupas says:

You should not hard-core any path. This is a bad practice. Use NSSearchPathForDirectoriesInDomains to locate the Application Support folders, and -[NSBundle builtInPlugInsPath] for the internal path.

Name

Website

Do you hate spammers? (Answer "Yes")