2 * Copyright (c) 2014 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-2014, 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 CF_PRIVATE
void __CFPFactoryInitialize(void) {
65 static dispatch_once_t initOnce
;
66 dispatch_once(&initOnce
, ^{ __kCFPFactoryTypeID
= _CFRuntimeRegisterClass(&__CFPFactoryClass
); });
69 static CFTypeID
_CFPFactoryGetTypeID(void) {
70 return __kCFPFactoryTypeID
;
73 static CFLock_t CFPlugInGlobalDataLock
= CFLockInit
;
74 static CFMutableDictionaryRef _factoriesByFactoryID
= NULL
; /* Value is _CFPFactoryRef */
75 static CFMutableDictionaryRef _factoriesByTypeID
= NULL
; /* Value is array of _CFPFactoryRef */
77 static void _CFPFactoryAddToTable(_CFPFactoryRef factory
) {
78 __CFLock(&factory
->_lock
);
79 CFUUIDRef uuid
= (CFUUIDRef
)CFRetain(factory
->_uuid
);
81 __CFUnlock(&factory
->_lock
);
83 __CFLock(&CFPlugInGlobalDataLock
);
84 if (!_factoriesByFactoryID
) {
85 CFDictionaryValueCallBacks _factoryDictValueCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
86 _factoriesByFactoryID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &_factoryDictValueCallbacks
);
88 CFDictionarySetValue(_factoriesByFactoryID
, uuid
, factory
);
89 __CFUnlock(&CFPlugInGlobalDataLock
);
91 if (uuid
) CFRelease(uuid
);
95 static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory
) {
96 __CFLock(&factory
->_lock
);
97 CFUUIDRef uuid
= factory
->_uuid
;
98 if (uuid
) CFRetain(uuid
);
99 __CFUnlock(&factory
->_lock
);
101 __CFLock(&CFPlugInGlobalDataLock
);
102 if (uuid
&& _factoriesByTypeID
) CFDictionaryRemoveValue(_factoriesByFactoryID
, uuid
);
103 __CFUnlock(&CFPlugInGlobalDataLock
);
105 if (uuid
) CFRelease(uuid
);
108 CF_PRIVATE _CFPFactoryRef
_CFPFactoryFind(CFUUIDRef factoryID
, Boolean enabled
) {
109 _CFPFactoryRef result
= NULL
;
111 __CFLock(&CFPlugInGlobalDataLock
);
112 if (_factoriesByFactoryID
) {
113 result
= (_CFPFactoryRef
)CFDictionaryGetValue(_factoriesByFactoryID
, factoryID
);
114 if (result
&& result
->_enabled
!= enabled
) result
= NULL
;
116 __CFUnlock(&CFPlugInGlobalDataLock
);
120 static void _CFPFactoryDeallocate(CFTypeRef ty
) {
122 _CFPFactoryRef factory
= (_CFPFactoryRef
)ty
;
124 _CFPFactoryRemoveFromTable(factory
);
126 if (factory
->_plugIn
) {
127 _CFPlugInRemoveFactory(factory
->_plugIn
, factory
);
128 CFRelease(factory
->_plugIn
);
131 /* Remove all types for this factory. */
132 c
= CFArrayGetCount(factory
->_types
);
133 while (c
-- > 0) _CFPFactoryRemoveType(factory
, (CFUUIDRef
)CFArrayGetValueAtIndex(factory
->_types
, c
));
134 CFRelease(factory
->_types
);
136 if (factory
->_funcName
) CFRelease(factory
->_funcName
);
137 if (factory
->_uuid
) CFRelease(factory
->_uuid
);
140 static _CFPFactoryRef
_CFPFactoryCommonCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
) {
141 _CFPFactoryRef factory
;
143 size
= sizeof(struct __CFPFactory
) - sizeof(CFRuntimeBase
);
144 factory
= (_CFPFactoryRef
)_CFRuntimeCreateInstance(allocator
, _CFPFactoryGetTypeID(), size
, NULL
);
145 if (!factory
) return NULL
;
147 factory
->_uuid
= (CFUUIDRef
)CFRetain(factoryID
);
148 factory
->_enabled
= true;
149 factory
->_types
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
150 factory
->_lock
= CFLockInit
; // WARNING: grab global lock before this lock
152 _CFPFactoryAddToTable(factory
);
157 CF_PRIVATE _CFPFactoryRef
_CFPFactoryCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInFactoryFunction func
) {
158 _CFPFactoryRef factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
160 __CFLock(&factory
->_lock
);
161 factory
->_func
= func
;
162 factory
->_plugIn
= NULL
;
163 factory
->_funcName
= NULL
;
164 __CFUnlock(&factory
->_lock
);
169 CF_PRIVATE _CFPFactoryRef
_CFPFactoryCreateByName(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInRef plugIn
, CFStringRef funcName
) {
170 _CFPFactoryRef factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
172 __CFLock(&factory
->_lock
);
173 factory
->_func
= NULL
;
174 factory
->_plugIn
= (CFPlugInRef
)CFRetain(plugIn
);
175 if (plugIn
) _CFPlugInAddFactory(plugIn
, factory
);
176 factory
->_funcName
= (funcName
? (CFStringRef
)CFStringCreateCopy(allocator
, funcName
) : NULL
);
177 __CFUnlock(&factory
->_lock
);
182 CF_PRIVATE CFUUIDRef
_CFPFactoryCopyFactoryID(_CFPFactoryRef factory
) {
183 __CFLock(&factory
->_lock
);
184 CFUUIDRef uuid
= factory
->_uuid
;
185 if (uuid
) CFRetain(uuid
);
186 __CFUnlock(&factory
->_lock
);
190 CF_PRIVATE CFPlugInRef
_CFPFactoryCopyPlugIn(_CFPFactoryRef factory
) {
191 __CFLock(&factory
->_lock
);
192 CFPlugInRef result
= factory
->_plugIn
;
193 if (result
) CFRetain(result
);
194 __CFUnlock(&factory
->_lock
);
198 CF_PRIVATE
void *_CFPFactoryCreateInstance(CFAllocatorRef allocator
, _CFPFactoryRef factory
, CFUUIDRef typeID
) {
201 __CFLock(&factory
->_lock
);
202 if (factory
->_enabled
) {
203 if (!factory
->_func
) {
204 factory
->_func
= (CFPlugInFactoryFunction
)CFBundleGetFunctionPointerForName(factory
->_plugIn
, factory
->_funcName
);
205 if (!factory
->_func
) CFLog(__kCFLogPlugIn
, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory
->_funcName
, factory
->_uuid
, factory
->_plugIn
);
207 if (factory
->_func
) {
209 CFPlugInFactoryFunction f
= factory
->_func
;
210 __CFUnlock(&factory
->_lock
);
211 FAULT_CALLBACK((void **)&(f
));
212 result
= (void *)INVOKE_CALLBACK2(f
, allocator
, typeID
);
213 __CFLock(&factory
->_lock
);
216 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
218 __CFUnlock(&factory
->_lock
);
223 CF_PRIVATE
void _CFPFactoryDisable(_CFPFactoryRef factory
) {
224 __CFLock(&factory
->_lock
);
225 factory
->_enabled
= false;
226 __CFUnlock(&factory
->_lock
);
230 CF_PRIVATE
void _CFPFactoryFlushFunctionCache(_CFPFactoryRef factory
) {
231 /* MF:!!! Assert that this factory belongs to a plugIn. */
232 /* This is called by the factory's plugIn when the plugIn unloads its code. */
233 __CFLock(&factory
->_lock
);
234 factory
->_func
= NULL
;
235 __CFUnlock(&factory
->_lock
);
238 CF_PRIVATE
void _CFPFactoryAddType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
239 /* Add the factory to the type's array of factories */
240 __CFLock(&factory
->_lock
);
241 /* Add the type to the factory's type list */
242 CFArrayAppendValue(factory
->_types
, typeID
);
243 __CFUnlock(&factory
->_lock
);
245 __CFLock(&CFPlugInGlobalDataLock
);
246 if (!_factoriesByTypeID
) _factoriesByTypeID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
247 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
249 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
250 // Create this from default allocator
251 array
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &_factoryArrayCallbacks
);
252 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
255 CFArrayAppendValue(array
, factory
);
256 __CFUnlock(&CFPlugInGlobalDataLock
);
259 CF_PRIVATE
void _CFPFactoryRemoveType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
260 /* Remove it from the factory's type list */
263 __CFLock(&factory
->_lock
);
264 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
265 if (idx
>= 0) CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
266 __CFUnlock(&factory
->_lock
);
268 /* Remove the factory from the type's list of factories */
269 __CFLock(&CFPlugInGlobalDataLock
);
270 if (_factoriesByTypeID
) {
271 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
273 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
275 CFArrayRemoveValueAtIndex(array
, idx
);
276 if (CFArrayGetCount(array
) == 0) CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
280 __CFUnlock(&CFPlugInGlobalDataLock
);
283 CF_PRIVATE Boolean
_CFPFactorySupportsType(_CFPFactoryRef factory
, CFUUIDRef typeID
) {
286 __CFLock(&factory
->_lock
);
287 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
288 __CFUnlock(&factory
->_lock
);
290 return (idx
>= 0 ? true : false);
293 CF_PRIVATE CFArrayRef
_CFPFactoryFindCopyForType(CFUUIDRef typeID
) {
294 CFArrayRef result
= NULL
;
295 __CFLock(&CFPlugInGlobalDataLock
);
296 if (_factoriesByTypeID
) {
297 result
= (CFArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
298 if (result
) CFRetain(result
);
300 __CFUnlock(&CFPlugInGlobalDataLock
);
305 /* 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. */
306 CF_PRIVATE
void _CFPFactoryAddInstance(_CFPFactoryRef factory
) {
307 /* MF:!!! Assert that factory is enabled. */
309 __CFLock(&factory
->_lock
);
310 CFPlugInRef plugin
= factory
->_plugIn
;
311 if (plugin
) CFRetain(plugin
);
312 __CFUnlock(&factory
->_lock
);
314 _CFPlugInAddPlugInInstance(plugin
);
319 CF_PRIVATE
void _CFPFactoryRemoveInstance(_CFPFactoryRef factory
) {
320 __CFLock(&factory
->_lock
);
321 CFPlugInRef plugin
= factory
->_plugIn
;
322 if (plugin
) CFRetain(plugin
);
323 __CFUnlock(&factory
->_lock
);
325 _CFPlugInRemovePlugInInstance(factory
->_plugIn
);