#include "CFBundle_Internal.h"
#include "CFInternal.h"
static void _registerFactory(const void *key, const void *val, void *context) {
CFStringRef factoryIDStr = (CFStringRef)key;
CFStringRef factoryFuncStr = (CFStringRef)val;
CFBundleRef bundle = (CFBundleRef)context;
CFUUIDRef factoryID = (CFGetTypeID(factoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(kCFAllocatorSystemDefault, factoryIDStr) : NULL;
if (!factoryID) factoryID = (CFUUIDRef)CFRetain(factoryIDStr);
if (CFGetTypeID(factoryFuncStr) != CFStringGetTypeID() || CFStringGetLength(factoryFuncStr) <= 0) factoryFuncStr = NULL;
CFPlugInRegisterFactoryFunctionByName(factoryID, bundle, factoryFuncStr);
if (factoryID) CFRelease(factoryID);
}
static void _registerType(const void *key, const void *val, void *context) {
CFStringRef typeIDStr = (CFStringRef)key;
CFArrayRef factoryIDStrArray = (CFArrayRef)val;
CFBundleRef bundle = (CFBundleRef)context;
SInt32 i, c = (CFGetTypeID(factoryIDStrArray) == CFArrayGetTypeID()) ? CFArrayGetCount(factoryIDStrArray) : 0;
CFStringRef curFactoryIDStr;
CFUUIDRef typeID = (CFGetTypeID(typeIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(kCFAllocatorSystemDefault, typeIDStr) : NULL;
CFUUIDRef curFactoryID;
if (!typeID) typeID = (CFUUIDRef)CFRetain(typeIDStr);
if (0 == c && CFGetTypeID(factoryIDStrArray) != CFArrayGetTypeID()) {
curFactoryIDStr = (CFStringRef)val;
curFactoryID = (CFGetTypeID(curFactoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(CFGetAllocator(bundle), curFactoryIDStr) : NULL;
if (!curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
CFPlugInRegisterPlugInType(curFactoryID, typeID);
if (curFactoryID) CFRelease(curFactoryID);
} else for (i = 0; i < c; i++) {
curFactoryIDStr = (CFStringRef)CFArrayGetValueAtIndex(factoryIDStrArray, i);
curFactoryID = (CFGetTypeID(curFactoryIDStr) == CFStringGetTypeID()) ? CFUUIDCreateFromString(CFGetAllocator(bundle), curFactoryIDStr) : NULL;
if (!curFactoryID) curFactoryID = (CFUUIDRef)CFRetain(curFactoryIDStr);
CFPlugInRegisterPlugInType(curFactoryID, typeID);
if (curFactoryID) CFRelease(curFactoryID);
}
if (typeID) CFRelease(typeID);
}
__private_extern__ Boolean _CFBundleNeedsInitPlugIn(CFBundleRef bundle) {
Boolean result = false;
CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle), factoryDict;
CFStringRef tempStr;
if (infoDict) {
factoryDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInFactoriesKey);
if (factoryDict && CFGetTypeID(factoryDict) == CFDictionaryGetTypeID()) result = true;
tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegistrationKey);
if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) result = true;
}
return result;
}
__private_extern__ void _CFBundleInitPlugIn(CFBundleRef bundle) {
CFArrayCallBacks _pluginFactoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
Boolean doDynamicReg = false;
CFDictionaryRef infoDict;
CFDictionaryRef factoryDict;
CFDictionaryRef typeDict;
CFStringRef tempStr;
infoDict = CFBundleGetInfoDictionary(bundle);
if (!infoDict) return;
factoryDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInFactoriesKey);
if (factoryDict && CFGetTypeID(factoryDict) != CFDictionaryGetTypeID()) factoryDict = NULL;
tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegistrationKey);
if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) doDynamicReg = true;
if (!factoryDict && !doDynamicReg) return;
__CFBundleGetPlugInData(bundle)->_isPlugIn = true;
__CFBundleGetPlugInData(bundle)->_loadOnDemand = true;
__CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration = false;
__CFBundleGetPlugInData(bundle)->_instanceCount = 0;
__CFBundleGetPlugInData(bundle)->_factories = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &_pluginFactoryArrayCallbacks);
if (factoryDict) CFDictionaryApplyFunction(factoryDict, _registerFactory, bundle);
typeDict = (CFDictionaryRef)CFDictionaryGetValue(infoDict, kCFPlugInTypesKey);
if (typeDict && CFGetTypeID(typeDict) != CFDictionaryGetTypeID()) typeDict = NULL;
if (typeDict) CFDictionaryApplyFunction(typeDict, _registerType, bundle);
if (doDynamicReg) {
CFDictionarySetValue((CFMutableDictionaryRef)infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"), CFSTR("YES"));
if (CFBundleIsExecutableLoaded(bundle)) _CFBundlePlugInLoaded(bundle);
}
}
__private_extern__ void _CFBundlePlugInLoaded(CFBundleRef bundle) {
CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
CFStringRef tempStr;
CFPlugInDynamicRegisterFunction func = NULL;
if (!__CFBundleGetPlugInData(bundle)->_isPlugIn || __CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration || !infoDict || !CFBundleIsExecutableLoaded(bundle)) return;
tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
if (tempStr && CFGetTypeID(tempStr) == CFStringGetTypeID() && CFStringCompare(tempStr, CFSTR("YES"), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
tempStr = (CFStringRef)CFDictionaryGetValue(infoDict, kCFPlugInDynamicRegisterFunctionKey);
if (!tempStr || CFGetTypeID(tempStr) != CFStringGetTypeID() || CFStringGetLength(tempStr) <= 0) tempStr = CFSTR("CFPlugInDynamicRegister");
__CFBundleGetPlugInData(bundle)->_loadOnDemand = false;
__CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration = true;
func = (CFPlugInDynamicRegisterFunction)CFBundleGetFunctionPointerForName(bundle, tempStr);
if (func) {
func(bundle);
}
__CFBundleGetPlugInData(bundle)->_isDoingDynamicRegistration = false;
if (__CFBundleGetPlugInData(bundle)->_loadOnDemand && __CFBundleGetPlugInData(bundle)->_instanceCount == 0) CFBundleUnloadExecutable(bundle); } else {
CFDictionaryRemoveValue((CFMutableDictionaryRef)infoDict, CFSTR("CFPlugInNeedsDynamicRegistration"));
}
}
__private_extern__ void _CFBundleDeallocatePlugIn(CFBundleRef bundle) {
if (__CFBundleGetPlugInData(bundle)->_isPlugIn) {
SInt32 c;
c = CFArrayGetCount(__CFBundleGetPlugInData(bundle)->_factories);
while (c-- > 0) _CFPFactoryDisable((_CFPFactoryRef)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(bundle)->_factories, c));
CFRelease(__CFBundleGetPlugInData(bundle)->_factories);
__CFBundleGetPlugInData(bundle)->_isPlugIn = false;
}
}
CFTypeID CFPlugInGetTypeID(void) {
return CFBundleGetTypeID();
}
CFPlugInRef CFPlugInCreate(CFAllocatorRef allocator, CFURLRef plugInURL) {
CFBundleRef bundle = CFBundleCreate(allocator, plugInURL);
return (CFPlugInRef)bundle;
}
CFBundleRef CFPlugInGetBundle(CFPlugInRef plugIn) {
return (CFBundleRef)plugIn;
}
void CFPlugInSetLoadOnDemand(CFPlugInRef plugIn, Boolean flag) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
__CFBundleGetPlugInData(plugIn)->_loadOnDemand = flag;
if (__CFBundleGetPlugInData(plugIn)->_loadOnDemand && !__CFBundleGetPlugInData(plugIn)->_isDoingDynamicRegistration && __CFBundleGetPlugInData(plugIn)->_instanceCount == 0) {
CFBundleUnloadExecutable(plugIn);
} else if (!__CFBundleGetPlugInData(plugIn)->_loadOnDemand) {
CFBundleLoadExecutable(plugIn);
}
}
}
Boolean CFPlugInIsLoadOnDemand(CFPlugInRef plugIn) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
return __CFBundleGetPlugInData(plugIn)->_loadOnDemand;
} else {
return false;
}
}
__private_extern__ void _CFPlugInWillUnload(CFPlugInRef plugIn) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
SInt32 c = CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories);
while (c-- > 0) _CFPFactoryFlushFunctionCache((_CFPFactoryRef)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, c));
}
}
__private_extern__ void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
if (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0 && __CFBundleGetPlugInData(plugIn)->_loadOnDemand) _CFBundleUnscheduleForUnloading(CFPlugInGetBundle(plugIn)); __CFBundleGetPlugInData(plugIn)->_instanceCount++;
CFRetain(plugIn);
}
}
__private_extern__ void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
__CFBundleGetPlugInData(plugIn)->_instanceCount--;
if (__CFBundleGetPlugInData(plugIn)->_instanceCount == 0 && __CFBundleGetPlugInData(plugIn)->_loadOnDemand) {
_CFBundleScheduleForUnloading(CFPlugInGetBundle(plugIn));
}
CFRelease(plugIn);
}
}
__private_extern__ void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) CFArrayAppendValue(__CFBundleGetPlugInData(plugIn)->_factories, factory);
}
__private_extern__ void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
SInt32 idx = CFArrayGetFirstIndexOfValue(__CFBundleGetPlugInData(plugIn)->_factories, CFRangeMake(0, CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories)), factory);
if (idx >= 0) CFArrayRemoveValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, idx);
}
}