2 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 1999-2011, Apple Inc. All rights reserved.
26 Responsibility: David Smith
29 #include "CFBundle_Internal.h"
30 #include "CFInternal.h"
32 static CFSpinLock_t CFPlugInGlobalDataLock
= CFSpinLockInit
;
33 static CFMutableDictionaryRef _factoriesByFactoryID
= NULL
; /* Value is _CFPFactory */
34 static CFMutableDictionaryRef _factoriesByTypeID
= NULL
; /* Value is array of _CFPFactory */
36 static void _CFPFactoryAddToTable(_CFPFactory
*factory
) {
37 __CFSpinLock(&CFPlugInGlobalDataLock
);
38 if (!_factoriesByFactoryID
) {
39 CFDictionaryValueCallBacks _factoryDictValueCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
40 _factoriesByFactoryID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &_factoryDictValueCallbacks
);
42 CFDictionarySetValue(_factoriesByFactoryID
, factory
->_uuid
, factory
);
43 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
46 static void _CFPFactoryRemoveFromTable(_CFPFactory
*factory
) {
47 __CFSpinLock(&CFPlugInGlobalDataLock
);
48 if (_factoriesByFactoryID
) CFDictionaryRemoveValue(_factoriesByFactoryID
, factory
->_uuid
);
49 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
52 __private_extern__ _CFPFactory
*_CFPFactoryFind(CFUUIDRef factoryID
, Boolean enabled
) {
53 _CFPFactory
*result
= NULL
;
55 __CFSpinLock(&CFPlugInGlobalDataLock
);
56 if (_factoriesByFactoryID
) {
57 result
= (_CFPFactory
*)CFDictionaryGetValue(_factoriesByFactoryID
, factoryID
);
58 if (result
&& result
->_enabled
!= enabled
) result
= NULL
;
60 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
64 static void _CFPFactoryDeallocate(_CFPFactory
*factory
) {
65 CFAllocatorRef allocator
= factory
->_allocator
;
68 _CFPFactoryRemoveFromTable(factory
);
70 if (factory
->_plugIn
) _CFPlugInRemoveFactory(factory
->_plugIn
, factory
);
72 /* Remove all types for this factory. */
73 c
= CFArrayGetCount(factory
->_types
);
74 while (c
-- > 0) _CFPFactoryRemoveType(factory
, (CFUUIDRef
)CFArrayGetValueAtIndex(factory
->_types
, c
));
75 CFRelease(factory
->_types
);
77 if (factory
->_funcName
) CFRelease(factory
->_funcName
);
78 if (factory
->_uuid
) CFRelease(factory
->_uuid
);
80 CFAllocatorDeallocate(allocator
, factory
);
84 static _CFPFactory
*_CFPFactoryCommonCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
) {
87 size
= sizeof(_CFPFactory
);
88 allocator
= (allocator
? (CFAllocatorRef
)CFRetain(allocator
) : (CFAllocatorRef
)CFRetain(__CFGetDefaultAllocator()));
89 factory
= (_CFPFactory
*)CFAllocatorAllocate(allocator
, size
, 0);
95 factory
->_allocator
= allocator
;
96 factory
->_uuid
= (CFUUIDRef
)CFRetain(factoryID
);
97 factory
->_enabled
= true;
98 factory
->_instanceCount
= 0;
100 _CFPFactoryAddToTable(factory
);
102 factory
->_types
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
107 __private_extern__ _CFPFactory
*_CFPFactoryCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInFactoryFunction func
) {
108 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
110 factory
->_func
= func
;
111 factory
->_plugIn
= NULL
;
112 factory
->_funcName
= NULL
;
117 __private_extern__ _CFPFactory
*_CFPFactoryCreateByName(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInRef plugIn
, CFStringRef funcName
) {
118 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
120 factory
->_func
= NULL
;
121 factory
->_plugIn
= plugIn
;
122 if (plugIn
) _CFPlugInAddFactory(plugIn
, factory
);
123 factory
->_funcName
= (funcName
? (CFStringRef
)CFStringCreateCopy(allocator
, funcName
) : NULL
);
128 __private_extern__ CFUUIDRef
_CFPFactoryGetFactoryID(_CFPFactory
*factory
) {
129 return factory
->_uuid
;
132 __private_extern__ CFPlugInRef
_CFPFactoryGetPlugIn(_CFPFactory
*factory
) {
133 return factory
->_plugIn
;
136 __private_extern__
void *_CFPFactoryCreateInstance(CFAllocatorRef allocator
, _CFPFactory
*factory
, CFUUIDRef typeID
) {
138 if (factory
->_enabled
) {
139 if (!factory
->_func
) {
140 factory
->_func
= (CFPlugInFactoryFunction
)CFBundleGetFunctionPointerForName(factory
->_plugIn
, factory
->_funcName
);
141 if (!factory
->_func
) CFLog(__kCFLogPlugIn
, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory
->_funcName
, factory
->_uuid
, factory
->_plugIn
);
143 if (factory
->_func
) {
145 FAULT_CALLBACK((void **)&(factory
->_func
));
146 result
= (void *)INVOKE_CALLBACK2(factory
->_func
, allocator
, typeID
);
149 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
154 __private_extern__
void _CFPFactoryDisable(_CFPFactory
*factory
) {
155 factory
->_enabled
= false;
156 if (factory
->_instanceCount
== 0) _CFPFactoryDeallocate(factory
);
159 __private_extern__ Boolean
_CFPFactoryIsEnabled(_CFPFactory
*factory
) {
160 return factory
->_enabled
;
163 __private_extern__
void _CFPFactoryFlushFunctionCache(_CFPFactory
*factory
) {
164 /* MF:!!! Assert that this factory belongs to a plugIn. */
165 /* This is called by the factory's plugIn when the plugIn unloads its code. */
166 factory
->_func
= NULL
;
169 __private_extern__
void _CFPFactoryAddType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
170 CFMutableArrayRef array
;
172 /* Add the type to the factory's type list */
173 CFArrayAppendValue(factory
->_types
, typeID
);
175 /* Add the factory to the type's array of factories */
176 __CFSpinLock(&CFPlugInGlobalDataLock
);
177 if (!_factoriesByTypeID
) _factoriesByTypeID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
178 array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
180 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
181 // Create this from default allocator
182 array
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &_factoryArrayCallbacks
);
183 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
186 CFArrayAppendValue(array
, factory
);
187 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
190 __private_extern__
void _CFPFactoryRemoveType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
191 /* Remove it from the factory's type list */
194 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
195 if (idx
>= 0) CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
197 /* Remove the factory from the type's list of factories */
198 __CFSpinLock(&CFPlugInGlobalDataLock
);
199 if (_factoriesByTypeID
) {
200 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
202 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
204 CFArrayRemoveValueAtIndex(array
, idx
);
205 if (CFArrayGetCount(array
) == 0) CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
209 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
212 __private_extern__ Boolean
_CFPFactorySupportsType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
215 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
216 return (idx
>= 0 ? true : false);
219 __private_extern__ CFArrayRef
_CFPFactoryFindForType(CFUUIDRef typeID
) {
220 CFArrayRef result
= NULL
;
222 __CFSpinLock(&CFPlugInGlobalDataLock
);
223 if (_factoriesByTypeID
) result
= (CFArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
224 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
229 /* These methods are called by CFPlugInInstance when an instance is created or destroyed. If a factory's instance count goes to 0 and the factory has been disabled, the factory is destroyed. */
230 __private_extern__
void _CFPFactoryAddInstance(_CFPFactory
*factory
) {
231 /* MF:!!! Assert that factory is enabled. */
232 factory
->_instanceCount
++;
233 if (factory
->_plugIn
) _CFPlugInAddPlugInInstance(factory
->_plugIn
);
236 __private_extern__
void _CFPFactoryRemoveInstance(_CFPFactory
*factory
) {
237 /* MF:!!! Assert that _instanceCount > 0. */
238 factory
->_instanceCount
--;
239 if (factory
->_plugIn
) _CFPlugInRemovePlugInInstance(factory
->_plugIn
);
240 if (factory
->_instanceCount
== 0 && !factory
->_enabled
) _CFPFactoryDeallocate(factory
);