2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 Copyright 1999-2002, Apple, Inc. All rights reserved.
27 Responsibility: Doug Davidson
30 #include "CFBundle_Internal.h"
31 #include "CFInternal.h"
33 static CFSpinLock_t CFPlugInGlobalDataLock
= 0;
34 static CFMutableDictionaryRef _factoriesByFactoryID
= NULL
; /* Value is _CFPFactory */
35 static CFMutableDictionaryRef _factoriesByTypeID
= NULL
; /* Value is array of _CFPFactory */
37 static void _CFPFactoryAddToTable(_CFPFactory
*factory
) {
38 __CFSpinLock(&CFPlugInGlobalDataLock
);
39 if (_factoriesByFactoryID
== NULL
) {
40 CFDictionaryValueCallBacks _factoryDictValueCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
41 // Use default allocator
42 _factoriesByFactoryID
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &_factoryDictValueCallbacks
);
44 CFDictionarySetValue(_factoriesByFactoryID
, factory
->_uuid
, factory
);
45 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
48 static void _CFPFactoryRemoveFromTable(_CFPFactory
*factory
) {
49 __CFSpinLock(&CFPlugInGlobalDataLock
);
50 if (_factoriesByFactoryID
!= NULL
) {
51 CFDictionaryRemoveValue(_factoriesByFactoryID
, factory
->_uuid
);
53 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
56 __private_extern__ _CFPFactory
*_CFPFactoryFind(CFUUIDRef factoryID
, Boolean enabled
) {
57 _CFPFactory
*result
= NULL
;
59 __CFSpinLock(&CFPlugInGlobalDataLock
);
60 if (_factoriesByFactoryID
!= NULL
) {
61 result
= (_CFPFactory
*)CFDictionaryGetValue(_factoriesByFactoryID
, factoryID
);
62 if (result
&& result
->_enabled
!= enabled
) {
66 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
70 static void _CFPFactoryDeallocate(_CFPFactory
*factory
) {
71 CFAllocatorRef allocator
= factory
->_allocator
;
74 _CFPFactoryRemoveFromTable(factory
);
76 if (factory
->_plugIn
) {
77 _CFPlugInRemoveFactory(factory
->_plugIn
, factory
);
80 /* Remove all types for this factory. */
81 c
= CFArrayGetCount(factory
->_types
);
83 _CFPFactoryRemoveType(factory
, CFArrayGetValueAtIndex(factory
->_types
, c
));
85 CFRelease(factory
->_types
);
87 if (factory
->_funcName
) {
88 CFRelease(factory
->_funcName
);
92 CFRelease(factory
->_uuid
);
95 CFAllocatorDeallocate(allocator
, factory
);
99 static _CFPFactory
*_CFPFactoryCommonCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
) {
100 _CFPFactory
*factory
;
102 size
= sizeof(_CFPFactory
);
103 allocator
= ((NULL
== allocator
) ? CFRetain(__CFGetDefaultAllocator()) : CFRetain(allocator
));
104 factory
= CFAllocatorAllocate(allocator
, size
, 0);
105 if (NULL
== factory
) {
106 CFRelease(allocator
);
110 factory
->_allocator
= allocator
;
112 factory
->_uuid
= CFRetain(factoryID
);
113 factory
->_enabled
= true;
114 factory
->_instanceCount
= 0;
116 _CFPFactoryAddToTable(factory
);
118 factory
->_types
= CFArrayCreateMutable(allocator
, 0, &kCFTypeArrayCallBacks
);
123 __private_extern__ _CFPFactory
*_CFPFactoryCreate(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInFactoryFunction func
) {
124 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
126 factory
->_func
= func
;
127 factory
->_plugIn
= NULL
;
128 factory
->_funcName
= NULL
;
133 __private_extern__ _CFPFactory
*_CFPFactoryCreateByName(CFAllocatorRef allocator
, CFUUIDRef factoryID
, CFPlugInRef plugIn
, CFStringRef funcName
) {
134 _CFPFactory
*factory
= _CFPFactoryCommonCreate(allocator
, factoryID
);
136 factory
->_func
= NULL
;
137 factory
->_plugIn
= plugIn
;
139 _CFPlugInAddFactory(plugIn
, factory
);
141 factory
->_funcName
= (funcName
? CFStringCreateCopy(allocator
, funcName
) : NULL
);
146 __private_extern__ CFUUIDRef
_CFPFactoryGetFactoryID(_CFPFactory
*factory
) {
147 return factory
->_uuid
;
150 __private_extern__ CFPlugInRef
_CFPFactoryGetPlugIn(_CFPFactory
*factory
) {
151 return factory
->_plugIn
;
154 __private_extern__
void *_CFPFactoryCreateInstance(CFAllocatorRef allocator
, _CFPFactory
*factory
, CFUUIDRef typeID
) {
156 if (factory
->_enabled
) {
157 if (factory
->_func
== NULL
) {
158 factory
->_func
= CFBundleGetFunctionPointerForName(factory
->_plugIn
, factory
->_funcName
);
159 if (factory
->_func
== NULL
) {
160 CFLog(__kCFLogPlugIn
, CFSTR("Cannot find function pointer %@ for factory %@ in %@"), factory
->_funcName
, factory
->_uuid
, factory
->_plugIn
);
162 #if defined(__MACH__) && defined(__ppc__)
164 // return values from CFBundleGetFunctionPointerForName will always be dyld, but
165 // we must force-fault them because pointers to glue code do not fault correctly
166 factory
->_func
= (void *)((unsigned long)(factory
->_func
) | 0x1);
170 if (factory
->_func
) {
173 FAULT_CALLBACK((void **)&(factory
->_func
));
174 result
= (void *)INVOKE_CALLBACK2(factory
->_func
, allocator
, typeID
);
176 result
= factory
->_func(allocator
, typeID
);
180 CFLog(__kCFLogPlugIn
, CFSTR("Factory %@ is disabled"), factory
->_uuid
);
185 __private_extern__
void _CFPFactoryDisable(_CFPFactory
*factory
) {
186 factory
->_enabled
= false;
187 if (factory
->_instanceCount
== 0) {
188 _CFPFactoryDeallocate(factory
);
192 __private_extern__ Boolean
_CFPFactoryIsEnabled(_CFPFactory
*factory
) {
193 return factory
->_enabled
;
196 __private_extern__
void _CFPFactoryFlushFunctionCache(_CFPFactory
*factory
) {
197 /* MF:!!! Assert that this factory belongs to a plugIn. */
198 /* This is called by the factory's plugIn when the plugIn unloads its code. */
199 factory
->_func
= NULL
;
202 __private_extern__
void _CFPFactoryAddType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
203 CFMutableArrayRef array
;
205 /* Add the type to the factory's type list */
206 CFArrayAppendValue(factory
->_types
, typeID
);
208 /* Add the factory to the type's array of factories */
209 __CFSpinLock(&CFPlugInGlobalDataLock
);
210 if (_factoriesByTypeID
== NULL
) {
211 // Create this from default allocator
212 _factoriesByTypeID
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
214 array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
216 CFArrayCallBacks _factoryArrayCallbacks
= {0, NULL
, NULL
, NULL
, NULL
};
217 // Create this from default allocator
218 array
= CFArrayCreateMutable(NULL
, 0, &_factoryArrayCallbacks
);
219 CFDictionarySetValue(_factoriesByTypeID
, typeID
, array
);
222 CFArrayAppendValue(array
, factory
);
223 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
226 __private_extern__
void _CFPFactoryRemoveType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
227 /* Remove it from the factory's type list */
230 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
232 CFArrayRemoveValueAtIndex(factory
->_types
, idx
);
235 /* Remove the factory from the type's list of factories */
236 __CFSpinLock(&CFPlugInGlobalDataLock
);
237 if (_factoriesByTypeID
!= NULL
) {
238 CFMutableArrayRef array
= (CFMutableArrayRef
)CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
240 idx
= CFArrayGetFirstIndexOfValue(array
, CFRangeMake(0, CFArrayGetCount(array
)), factory
);
242 CFArrayRemoveValueAtIndex(array
, idx
);
243 if (CFArrayGetCount(array
) == 0) {
244 CFDictionaryRemoveValue(_factoriesByTypeID
, typeID
);
249 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
252 __private_extern__ Boolean
_CFPFactorySupportsType(_CFPFactory
*factory
, CFUUIDRef typeID
) {
255 idx
= CFArrayGetFirstIndexOfValue(factory
->_types
, CFRangeMake(0, CFArrayGetCount(factory
->_types
)), typeID
);
256 return ((idx
>= 0) ? true : false);
259 __private_extern__ CFArrayRef
_CFPFactoryFindForType(CFUUIDRef typeID
) {
260 CFArrayRef result
= NULL
;
262 __CFSpinLock(&CFPlugInGlobalDataLock
);
263 if (_factoriesByTypeID
!= NULL
) {
264 result
= CFDictionaryGetValue(_factoriesByTypeID
, typeID
);
266 __CFSpinUnlock(&CFPlugInGlobalDataLock
);
271 /* 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. */
272 __private_extern__
void _CFPFactoryAddInstance(_CFPFactory
*factory
) {
273 /* MF:!!! Assert that factory is enabled. */
274 factory
->_instanceCount
++;
275 if (factory
->_plugIn
) {
276 _CFPlugInAddPlugInInstance(factory
->_plugIn
);
280 __private_extern__
void _CFPFactoryRemoveInstance(_CFPFactory
*factory
) {
281 /* MF:!!! Assert that _instanceCount > 0. */
282 factory
->_instanceCount
--;
283 if (factory
->_plugIn
) {
284 _CFPlugInRemovePlugInInstance(factory
->_plugIn
);
286 if ((factory
->_instanceCount
== 0) && (!factory
->_enabled
)) {
287 _CFPFactoryDeallocate(factory
);