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-2012, Apple Inc. All rights reserved.
26 Responsibility: Tony Parker
29 #include "CFBundle_Internal.h"
30 #include "CFInternal.h"
32 static CFTypeID __kCFPFactoryTypeID
= _kCFRuntimeNotATypeID
;
41 CFPlugInFactoryFunction _func
;
44 CFStringRef _funcName
;
46 CFMutableArrayRef _types
;
50 static void _CFPFactoryDeallocate(CFTypeRef factory
);
52 static const CFRuntimeClass __CFPFactoryClass
= {
57 _CFPFactoryDeallocate
,
60 NULL
, // formatting desc
64 __private_extern__
void __CFPFactoryInitialize(void) {
65 __kCFPFactoryTypeID
= _CFRuntimeRegisterClass(&__CFPFactoryClass
);
68 static CFTypeID
_CFPFactoryGetTypeID(void) {
69 return __kCFPFactoryTypeID
;
72 static CFSpinLock_t CFPlugInGlobalDataLock
= CFSpinLockInit
;
73 static CFMutableDictionaryRef _factoriesByFactoryID
= NULL
; /* Value is _CFPFactoryRef */
74 static CFMutableDictionaryRef _factoriesByTypeID
= NULL
; /* Value is array of _CFPFactoryRef */
76 static void _CFPFactoryAddToTable(_CFPFactoryRef factory
) {
77 __CFSpinLock(&factory
->_lock
);
78 CFUUIDRef uuid
= (CFUUIDRef
)CFRetain(factory
->_uuid
);
80 __CFSpinUnlock(&factory
->_lock
);
82 __CFSpinLock(&CFPlugInGlobalDataLock
);
83 if (!_factoriesByFactoryID
) {
84 CFDictionaryValueCallBacks _factoryDictValueCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
85 _factoriesByFactoryID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &_factoryDictValueCallbacks
);
87 CFDictionarySetValue(_factoriesByFactoryID
, uuid
, factory
);
88 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
90 if (uuid
) CFRelease(uuid
);
94 static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory
) {
95 __CFSpinLock(&factory
->_lock
);
96 CFUUIDRef uuid
= factory
->_uuid
;
97 if (uuid
) CFRetain(uuid
);
98 __CFSpinUnlock(&factory
->_lock
);
100 __CFSpinLock(&CFPlugInGlobalDataLock
);
101 if (uuid
&& _factoriesByTypeID
) CFDictionaryRemoveValue(_factoriesByFactoryID
, uuid
);
102 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
104 if (uuid
) CFRelease(uuid
);
107 __private_extern__ _CFPFactoryRef
_CFPFactoryFind(CFUUIDRef factoryID
, Boolean enabled
) {
108 _CFPFactoryRef result
= NULL
;
110 __CFSpinLock(&CFPlugInGlobalDataLock
);
111 if (_factoriesByFactoryID
) {
112 result
= (_CFPFactoryRef
)CFDictionaryGetValue(_factoriesByFactoryID
, factoryID
);
113 if (result
&& result
->_enabled
!= enabled
) result
= NULL
;
115 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
119 static void _CFPFactoryDeallocate(CFTypeRef ty
) {
121 _CFPFactoryRef factory
= (_CFPFactoryRef
)ty
;
123 _CFPFactoryRemoveFromTable(factory
);
125 if (factory
->_plugIn
) {
126 _CFPlugInRemoveFactory(factory
->_plugIn
, factory
);
127 CFRelease(factory
->_plugIn
);
130 /* Remove all types for this factory. */
131 c
= CFArrayGetCount(factory
->_types
);
132 while (c
-- > 0) _CFPFactoryRemoveType(factory
, (CFUUIDRef
)CFArrayGetValueAtIndex(factory
->_types
, c
));
133 CFRelease(factory
->_types
);
135 if (factory
->_funcName
) CFRelease(factory
->_funcName
);
136 if (factory
->_uuid
) CFRelease(factory
->_uuid
);
139 static _CFPFactoryRef
_CFPFactoryCommonCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
) {
140 _CFPFactoryRef factory
;
142 size
= sizeof(struct __CFPFactory
) - sizeof(CFRuntimeBase
);
143 factory
= (_CFPFactoryRef
)_CFRuntimeCreateInstance(allocator
, _CFPFactoryGetTypeID(), size
, NULL
);
144 if (!factory
) return NULL
;
146 factory
->_uuid
= (CFUUIDRef
)CFRetain(factoryID
);
147 factory
->_enabled
= true;
148 factory
->_types
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
149 factory
->_lock
= CFSpinLockInit
; // WARNING: grab global lock before this lock
151 _CFPFactoryAddToTable(factory
);
156 __private_extern__ _CFPFactoryRef
_CFPFactoryCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInFactoryFunction func
) {
157 _CFPFactoryRef factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
159 __CFSpinLock(&factory
->_lock
);
160 factory
->_func
= func
;
161 factory
->_plugIn
= NULL
;
162 factory
->_funcName
= NULL
;
163 __CFSpinUnlock(&factory
->_lock
);
168 __private_extern__ _CFPFactoryRef
_CFPFactoryCreateByName(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInRef plugIn
, CFStringRef funcName
) {
169 _CFPFactoryRef factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
171 __CFSpinLock(&factory
->_lock
);
172 factory
->_func
= NULL
;
173 factory
->_plugIn
= (CFPlugInRef
)CFRetain(plugIn
);
174 if (plugIn
) _CFPlugInAddFactory(plugIn
, factory
);
175 factory
->_funcName
= (funcName
? (CFStringRef
)CFStringCreateCopy(allocator
, funcName
) : NULL
);
176 __CFSpinUnlock(&factory
->_lock
);
181 __private_extern__ CFUUIDRef
_CFPFactoryCopyFactoryID(_CFPFactoryRef factory
) {
182 __CFSpinLock(&factory
->_lock
);
183 CFUUIDRef uuid
= factory
->_uuid
;
184 if (uuid
) CFRetain(uuid
);
185 __CFSpinUnlock(&factory
->_lock
);
189 __private_extern__ CFPlugInRef
_CFPFactoryCopyPlugIn(_CFPFactoryRef factory
) {
190 __CFSpinLock(&factory
->_lock
);
191 CFPlugInRef result
= factory
->_plugIn
;
192 if (result
) CFRetain(result
);
193 __CFSpinUnlock(&factory
->_lock
);
197 __private_extern__
void *_CFPFactoryCreateInstance(CFAllocatorRef allocator
, _CFPFactoryRef factory
, CFUUIDRef typeID
) {
200 __CFSpinLock(&factory
->_lock
);
201 if (factory
->_enabled
) {
202 if (!factory
->_func
) {
203 factory
->_func
= (CFPlugInFactoryFunction
)CFBundleGetFunctionPointerForName(factory
->_plugIn
, factory
->_funcName
);
204 if (!factory
->_func
) CFLog(__kCFLogPlugIn
, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory
->_funcName
, factory
->_uuid
, factory
->_plugIn
);
206 if (factory
->_func
) {
208 CFPlugInFactoryFunction f
= factory
->_func
;
209 __CFSpinUnlock(&factory
->_lock
);
210 FAULT_CALLBACK((void **)&(f
));
211 result
= (void *)INVOKE_CALLBACK2(f
, allocator
, typeID
);
212 __CFSpinLock(&factory
->_lock
);
215 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
217 __CFSpinUnlock(&factory
->_lock
);
222 __private_extern__
void _CFPFactoryDisable(_CFPFactoryRef factory
) {
223 __CFSpinLock(&factory
->_lock
);
224 factory
->_enabled
= false;
225 __CFSpinUnlock(&factory
->_lock
);
229 __private_extern__
void _CFPFactoryFlushFunctionCache(_CFPFactoryRef factory
) {
230 /* MF:!!! Assert that this factory belongs to a plugIn. */
231 /* This is called by the factory's plugIn when the plugIn unloads its code. */
232 __CFSpinLock(&factory
->_lock
);
233 factory
->_func
= NULL
;
234 __CFSpinUnlock(&factory
->_lock
);
237 __private_extern__
void _CFPFactoryAddType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
238 /* Add the factory to the type's array of factories */
239 __CFSpinLock(&factory
->_lock
);
240 /* Add the type to the factory's type list */
241 CFArrayAppendValue(factory
->_types
, typeID
);
242 __CFSpinUnlock(&factory
->_lock
);
244 __CFSpinLock(&CFPlugInGlobalDataLock
);
245 if (!_factoriesByTypeID
) _factoriesByTypeID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
246 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
248 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
249 // Create this from default allocator
250 array
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &_factoryArrayCallbacks
);
251 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
254 CFArrayAppendValue(array
, factory
);
255 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
258 __private_extern__
void _CFPFactoryRemoveType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
259 /* Remove it from the factory's type list */
262 __CFSpinLock(&factory
->_lock
);
263 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
264 if (idx
>= 0) CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
265 __CFSpinUnlock(&factory
->_lock
);
267 /* Remove the factory from the type's list of factories */
268 __CFSpinLock(&CFPlugInGlobalDataLock
);
269 if (_factoriesByTypeID
) {
270 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
272 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
274 CFArrayRemoveValueAtIndex(array
, idx
);
275 if (CFArrayGetCount(array
) == 0) CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
279 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
282 __private_extern__ Boolean
_CFPFactorySupportsType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
285 __CFSpinLock(&factory
->_lock
);
286 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
287 __CFSpinUnlock(&factory
->_lock
);
289 return (idx
>= 0 ? true : false);
292 __private_extern__ CFArrayRef
_CFPFactoryFindCopyForType(CFUUIDRef typeID
) {
293 CFArrayRef result
= NULL
;
294 __CFSpinLock(&CFPlugInGlobalDataLock
);
295 if (_factoriesByTypeID
) {
296 result
= (CFArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
297 if (result
) CFRetain(result
);
299 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
304 /* 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. */
305 __private_extern__
void _CFPFactoryAddInstance(_CFPFactoryRef factory
) {
306 /* MF:!!! Assert that factory is enabled. */
308 __CFSpinLock(&factory
->_lock
);
309 CFPlugInRef plugin
= factory
->_plugIn
;
310 if (plugin
) CFRetain(plugin
);
311 __CFSpinUnlock(&factory
->_lock
);
313 _CFPlugInAddPlugInInstance(plugin
);
318 __private_extern__
void _CFPFactoryRemoveInstance(_CFPFactoryRef factory
) {
319 __CFSpinLock(&factory
->_lock
);
320 CFPlugInRef plugin
= factory
->_plugIn
;
321 if (plugin
) CFRetain(plugin
);
322 __CFSpinUnlock(&factory
->_lock
);
324 _CFPlugInRemovePlugInInstance(factory
->_plugIn
);