2 * Copyright (c) 2008 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@
24 Copyright (c) 1999-2007 Apple Inc. All rights reserved.
25 Responsibility: Doug Davidson
28 #include "CFBundle_Internal.h"
29 #include "CFInternal.h"
31 static CFSpinLock_t CFPlugInGlobalDataLock
= CFSpinLockInit
;
32 static CFMutableDictionaryRef _factoriesByFactoryID
= NULL
; /* Value is _CFPFactory */
33 static CFMutableDictionaryRef _factoriesByTypeID
= NULL
; /* Value is array of _CFPFactory */
35 static void _CFPFactoryAddToTable(_CFPFactory
*factory
) {
36 __CFSpinLock(&CFPlugInGlobalDataLock
);
37 if (_factoriesByFactoryID
== NULL
) {
38 CFDictionaryValueCallBacks _factoryDictValueCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
39 // Use default allocator
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
!= NULL
) {
49 CFDictionaryRemoveValue(_factoriesByFactoryID
, factory
->_uuid
);
51 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
54 __private_extern__ _CFPFactory
*_CFPFactoryFind(CFUUIDRef factoryID
, Boolean enabled
) {
55 _CFPFactory
*result
= NULL
;
57 __CFSpinLock(&CFPlugInGlobalDataLock
);
58 if (_factoriesByFactoryID
!= NULL
) {
59 result
= (_CFPFactory
*)CFDictionaryGetValue(_factoriesByFactoryID
, factoryID
);
60 if (result
&& result
->_enabled
!= enabled
) {
64 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
68 static void _CFPFactoryDeallocate(_CFPFactory
*factory
) {
69 CFAllocatorRef allocator
= factory
->_allocator
;
72 _CFPFactoryRemoveFromTable(factory
);
74 if (factory
->_plugIn
) {
75 _CFPlugInRemoveFactory(factory
->_plugIn
, factory
);
78 /* Remove all types for this factory. */
79 c
= CFArrayGetCount(factory
->_types
);
81 _CFPFactoryRemoveType(factory
, (CFUUIDRef
)CFArrayGetValueAtIndex(factory
->_types
, c
));
83 CFRelease(factory
->_types
);
85 if (factory
->_funcName
) {
86 CFRelease(factory
->_funcName
);
90 CFRelease(factory
->_uuid
);
93 CFAllocatorDeallocate(allocator
, factory
);
97 static _CFPFactory
*_CFPFactoryCommonCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
) {
100 size
= sizeof(_CFPFactory
);
101 allocator
= ((NULL
== allocator
) ? (CFAllocatorRef
)CFRetain(__CFGetDefaultAllocator()) : (CFAllocatorRef
)CFRetain(allocator
));
102 factory
= (_CFPFactory
*)CFAllocatorAllocate(allocator
, size
, 0);
103 if (NULL
== factory
) {
104 CFRelease(allocator
);
108 factory
->_allocator
= allocator
;
110 factory
->_uuid
= (CFUUIDRef
)CFRetain(factoryID
);
111 factory
->_enabled
= true;
112 factory
->_instanceCount
= 0;
114 _CFPFactoryAddToTable(factory
);
116 factory
->_types
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
121 __private_extern__ _CFPFactory
*_CFPFactoryCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInFactoryFunction func
) {
122 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
124 factory
->_func
= func
;
125 factory
->_plugIn
= NULL
;
126 factory
->_funcName
= NULL
;
131 __private_extern__ _CFPFactory
*_CFPFactoryCreateByName(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInRef plugIn
, CFStringRef funcName
) {
132 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
134 factory
->_func
= NULL
;
135 factory
->_plugIn
= plugIn
;
137 _CFPlugInAddFactory(plugIn
, factory
);
139 factory
->_funcName
= (funcName
? (CFStringRef
)CFStringCreateCopy(allocator
, funcName
) : NULL
);
144 __private_extern__ CFUUIDRef
_CFPFactoryGetFactoryID(_CFPFactory
*factory
) {
145 return factory
->_uuid
;
148 __private_extern__ CFPlugInRef
_CFPFactoryGetPlugIn(_CFPFactory
*factory
) {
149 return factory
->_plugIn
;
152 __private_extern__
void *_CFPFactoryCreateInstance(CFAllocatorRef allocator
, _CFPFactory
*factory
, CFUUIDRef typeID
) {
154 if (factory
->_enabled
) {
155 if (factory
->_func
== NULL
) {
156 factory
->_func
= (CFPlugInFactoryFunction
)CFBundleGetFunctionPointerForName(factory
->_plugIn
, factory
->_funcName
);
157 if (factory
->_func
== NULL
) {
158 CFLog(__kCFLogPlugIn
, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory
->_funcName
, factory
->_uuid
, factory
->_plugIn
);
160 #if BINARY_SUPPORT_CFM
162 // return values from CFBundleGetFunctionPointerForName will always be dyld, but
163 // we must force-fault them because pointers to glue code do not fault correctly
164 factory
->_func
= (void *)((uint32_t)(factory
->_func
) | 0x1);
166 #endif /* BINARY_SUPPORT_CFM */
168 if (factory
->_func
) {
170 FAULT_CALLBACK((void **)&(factory
->_func
));
171 result
= (void *)INVOKE_CALLBACK2(factory
->_func
, allocator
, typeID
);
174 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
179 __private_extern__
void _CFPFactoryDisable(_CFPFactory
*factory
) {
180 factory
->_enabled
= false;
181 if (factory
->_instanceCount
== 0) {
182 _CFPFactoryDeallocate(factory
);
186 __private_extern__ Boolean
_CFPFactoryIsEnabled(_CFPFactory
*factory
) {
187 return factory
->_enabled
;
190 __private_extern__
void _CFPFactoryFlushFunctionCache(_CFPFactory
*factory
) {
191 /* MF:!!! Assert that this factory belongs to a plugIn. */
192 /* This is called by the factory's plugIn when the plugIn unloads its code. */
193 factory
->_func
= NULL
;
196 __private_extern__
void _CFPFactoryAddType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
197 CFMutableArrayRef array
;
199 /* Add the type to the factory's type list */
200 CFArrayAppendValue(factory
->_types
, typeID
);
202 /* Add the factory to the type's array of factories */
203 __CFSpinLock(&CFPlugInGlobalDataLock
);
204 if (_factoriesByTypeID
== NULL
) {
205 // Create this from default allocator
206 _factoriesByTypeID
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
208 array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
210 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
211 // Create this from default allocator
212 array
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &_factoryArrayCallbacks
);
213 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
216 CFArrayAppendValue(array
, factory
);
217 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
220 __private_extern__
void _CFPFactoryRemoveType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
221 /* Remove it from the factory's type list */
224 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
226 CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
229 /* Remove the factory from the type's list of factories */
230 __CFSpinLock(&CFPlugInGlobalDataLock
);
231 if (_factoriesByTypeID
!= NULL
) {
232 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
234 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
236 CFArrayRemoveValueAtIndex(array
, idx
);
237 if (CFArrayGetCount(array
) == 0) {
238 CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
243 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
246 __private_extern__ Boolean
_CFPFactorySupportsType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
249 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
250 return ((idx
>= 0) ? true : false);
253 __private_extern__ CFArrayRef
_CFPFactoryFindForType(CFUUIDRef typeID
) {
254 CFArrayRef result
= NULL
;
256 __CFSpinLock(&CFPlugInGlobalDataLock
);
257 if (_factoriesByTypeID
!= NULL
) {
258 result
= (CFArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
260 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
265 /* 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. */
266 __private_extern__
void _CFPFactoryAddInstance(_CFPFactory
*factory
) {
267 /* MF:!!! Assert that factory is enabled. */
268 factory
->_instanceCount
++;
269 if (factory
->_plugIn
) {
270 _CFPlugInAddPlugInInstance(factory
->_plugIn
);
274 __private_extern__
void _CFPFactoryRemoveInstance(_CFPFactory
*factory
) {
275 /* MF:!!! Assert that _instanceCount > 0. */
276 factory
->_instanceCount
--;
277 if (factory
->_plugIn
) {
278 _CFPlugInRemovePlugInInstance(factory
->_plugIn
);
280 if ((factory
->_instanceCount
== 0) && (!factory
->_enabled
)) {
281 _CFPFactoryDeallocate(factory
);