/*
    CategoryLoader.m
    ================

    John Holdsworth
    Coldwave Programs Ltd.

    This software is in the public domain.

    A class inteneded to be distributed to unload and reload bundles
    containing category inplementations. The message didLoad is sent
    to the principal class of the bundle for it to print it build date. 

*/
/*
 * $Log: CategoryLoader.m,v $
 * Revision 1.4  1997/04/14  23:02:30  johnh
 * Descriptions added.
 *
 * Revision 1.3  1997/04/14  22:46:04  johnh
 * New category just for DO created.
 *
 */

#import "CategoryLoader.h"
#import "ObjectDistributingCategory.h"

#import <objc/objc-load.h> // for objc_unloadModules()


@implementation CategoryLoader
/* simple class to load and reload class categories */
{
}

static void *unload( Class aClass, Category aCategory )
{
    if( aCategory )
	fprintf( stderr, "Unloading category %s of class %s\n", 
		aCategory->category_name, aCategory->class_name );
    else if( aClass )
	fprintf( stderr, "Unloading class %s\n", aClass->name );
    
    return (void *)0;
}

- (BOOL)reloadBundle:(const char *)bundlePath;
/* messaged to load bundle from bundle project Makefile.postamble. Unloads bundle if it has already been loaded and modifies path to fool NXBundle into creating a new instance even though bundle has already been loaded. */
{
    static int times = 0; // number of times bundle has been loaded
    char buffer[MAXPATHLEN]; // changing path of bundle
    SEL postLoad = @selector(didLoad);
    NXBundle *bundle;
    Class loadedClass;
    int count;

    /* reprend "./" n times to fool NXBundle into reloading */
    for( count = 0 ; count < times ; count++ )
	sprintf( buffer+count, "/" ); // to defeat NXBundle uniqueing

    sprintf( buffer+times, "%s", bundlePath );

    if( times > 0 ) // unload if already loaded
	objc_unloadModules( (NXStream *)0, (void (*)(Class, Category))unload );

    /* create new bundle instance */
    bundle = [[NXBundle alloc] initForDirectory:buffer];
    if( !bundle ) {
	fprintf( stdout, "Unable to initialise bundle %s\n", buffer );
	return NO;
    }

    loadedClass = [bundle principalClass];
    if( !loadedClass ) {
	fprintf( stdout, "Unable to load bundle %s\n", buffer );
	return NO;
    }
	
    if( [loadedClass respondsTo:postLoad] )
	[loadedClass perform:postLoad];

    times++;
    
    return loadedClass != (Class)0; // force load of object code
}

- init {
    self = [super init];

    [self runFromAppKit];

    return self;
}

@end
