2 * Copyright (c) 2005 Apple Computer, 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 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Doug Davidson
28 #include "CFBundle_Internal.h"
29 #include "CFInternal.h"
31 static CFSpinLock_t CFPlugInGlobalDataLock
= 0;
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(NULL
, 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
, 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
) ? CFRetain(__CFGetDefaultAllocator()) : CFRetain(allocator
));
102 factory
= CFAllocatorAllocate(allocator
, size
, 0);
103 if (NULL
== factory
) {
104 CFRelease(allocator
);
108 factory
->_allocator
= allocator
;
110 factory
->_uuid
= 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
? 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
= 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 defined(__MACH__) && defined(__ppc__)
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);
168 if (factory
->_func
) {
171 FAULT_CALLBACK((void **)&(factory
->_func
));
172 result
= (void *)INVOKE_CALLBACK2(factory
->_func
, allocator
, typeID
);
174 result
= factory
->_func(allocator
, typeID
);
178 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
183 __private_extern__
void _CFPFactoryDisable(_CFPFactory
*factory
) {
184 factory
->_enabled
= false;
185 if (factory
->_instanceCount
== 0) {
186 _CFPFactoryDeallocate(factory
);
190 __private_extern__ Boolean
_CFPFactoryIsEnabled(_CFPFactory
*factory
) {
191 return factory
->_enabled
;
194 __private_extern__
void _CFPFactoryFlushFunctionCache(_CFPFactory
*factory
) {
195 /* MF:!!! Assert that this factory belongs to a plugIn. */
196 /* This is called by the factory's plugIn when the plugIn unloads its code. */
197 factory
->_func
= NULL
;
200 __private_extern__
void _CFPFactoryAddType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
201 CFMutableArrayRef array
;
203 /* Add the type to the factory's type list */
204 CFArrayAppendValue(factory
->_types
, typeID
);
206 /* Add the factory to the type's array of factories */
207 __CFSpinLock(&CFPlugInGlobalDataLock
);
208 if (_factoriesByTypeID
== NULL
) {
209 // Create this from default allocator
210 _factoriesByTypeID
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
212 array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
214 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
215 // Create this from default allocator
216 array
= CFArrayCreateMutable(NULL
, 0, &_factoryArrayCallbacks
);
217 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
220 CFArrayAppendValue(array
, factory
);
221 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
224 __private_extern__
void _CFPFactoryRemoveType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
225 /* Remove it from the factory's type list */
228 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
230 CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
233 /* Remove the factory from the type's list of factories */
234 __CFSpinLock(&CFPlugInGlobalDataLock
);
235 if (_factoriesByTypeID
!= NULL
) {
236 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
238 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
240 CFArrayRemoveValueAtIndex(array
, idx
);
241 if (CFArrayGetCount(array
) == 0) {
242 CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
247 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
250 __private_extern__ Boolean
_CFPFactorySupportsType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
253 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
254 return ((idx
>= 0) ? true : false);
257 __private_extern__ CFArrayRef
_CFPFactoryFindForType(CFUUIDRef typeID
) {
258 CFArrayRef result
= NULL
;
260 __CFSpinLock(&CFPlugInGlobalDataLock
);
261 if (_factoriesByTypeID
!= NULL
) {
262 result
= CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
264 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
269 /* 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. */
270 __private_extern__
void _CFPFactoryAddInstance(_CFPFactory
*factory
) {
271 /* MF:!!! Assert that factory is enabled. */
272 factory
->_instanceCount
++;
273 if (factory
->_plugIn
) {
274 _CFPlugInAddPlugInInstance(factory
->_plugIn
);
278 __private_extern__
void _CFPFactoryRemoveInstance(_CFPFactory
*factory
) {
279 /* MF:!!! Assert that _instanceCount > 0. */
280 factory
->_instanceCount
--;
281 if (factory
->_plugIn
) {
282 _CFPlugInRemovePlugInInstance(factory
->_plugIn
);
284 if ((factory
->_instanceCount
== 0) && (!factory
->_enabled
)) {
285 _CFPFactoryDeallocate(factory
);