1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 // DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE()
42 #include "nsGenericFactory.h"
45 #include "nsIComponentManager.h"
46 #include "nsIComponentRegistrar.h"
47 #include "nsIProgrammingLanguage.h"
50 #include "nsXPCOMGlue.h"
51 #include "nsXPCOMPrivate.h"
54 nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo
*info
)
57 if (mInfo
&& mInfo
->mClassInfoGlobal
)
58 *mInfo
->mClassInfoGlobal
= static_cast<nsIClassInfo
*>(this);
61 nsGenericFactory::~nsGenericFactory()
64 if (mInfo
->mFactoryDestructor
)
65 mInfo
->mFactoryDestructor();
66 if (mInfo
->mClassInfoGlobal
)
67 *mInfo
->mClassInfoGlobal
= 0;
71 NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory
,
76 NS_IMETHODIMP
nsGenericFactory::CreateInstance(nsISupports
*aOuter
,
77 REFNSIID aIID
, void **aResult
)
79 if (mInfo
->mConstructor
) {
80 return mInfo
->mConstructor(aOuter
, aIID
, aResult
);
83 return NS_ERROR_FACTORY_NOT_REGISTERED
;
86 NS_IMETHODIMP
nsGenericFactory::LockFactory(PRBool aLock
)
88 // XXX do we care if (mInfo->mFlags & THREADSAFE)?
92 NS_IMETHODIMP
nsGenericFactory::GetInterfaces(PRUint32
*countp
,
95 if (!mInfo
->mGetInterfacesProc
) {
100 return mInfo
->mGetInterfacesProc(countp
, array
);
103 NS_IMETHODIMP
nsGenericFactory::GetHelperForLanguage(PRUint32 language
,
104 nsISupports
**helper
)
106 if (mInfo
->mGetLanguageHelperProc
)
107 return mInfo
->mGetLanguageHelperProc(language
, helper
);
112 NS_IMETHODIMP
nsGenericFactory::GetContractID(char **aContractID
)
114 if (mInfo
->mContractID
) {
115 *aContractID
= (char *)nsMemory::Alloc(strlen(mInfo
->mContractID
) + 1);
117 return NS_ERROR_OUT_OF_MEMORY
;
118 strcpy(*aContractID
, mInfo
->mContractID
);
120 *aContractID
= nsnull
;
125 NS_IMETHODIMP
nsGenericFactory::GetClassDescription(char * *aClassDescription
)
127 if (mInfo
->mDescription
) {
128 *aClassDescription
= (char *)
129 nsMemory::Alloc(strlen(mInfo
->mDescription
) + 1);
130 if (!*aClassDescription
)
131 return NS_ERROR_OUT_OF_MEMORY
;
132 strcpy(*aClassDescription
, mInfo
->mDescription
);
134 *aClassDescription
= nsnull
;
139 NS_IMETHODIMP
nsGenericFactory::GetClassID(nsCID
* *aClassID
)
142 reinterpret_cast<nsCID
*>
143 (nsMemory::Clone(&mInfo
->mCID
, sizeof mInfo
->mCID
));
145 return NS_ERROR_OUT_OF_MEMORY
;
149 NS_IMETHODIMP
nsGenericFactory::GetClassIDNoAlloc(nsCID
*aClassID
)
151 *aClassID
= mInfo
->mCID
;
155 NS_IMETHODIMP
nsGenericFactory::GetImplementationLanguage(PRUint32
*langp
)
157 *langp
= nsIProgrammingLanguage::CPLUSPLUS
;
161 NS_IMETHODIMP
nsGenericFactory::GetFlags(PRUint32
*flagsp
)
163 *flagsp
= mInfo
->mFlags
;
167 // nsIGenericFactory: component-info accessors
168 NS_IMETHODIMP
nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo
*info
)
170 if (mInfo
&& mInfo
->mClassInfoGlobal
)
171 *mInfo
->mClassInfoGlobal
= 0;
173 if (mInfo
&& mInfo
->mClassInfoGlobal
)
174 *mInfo
->mClassInfoGlobal
= static_cast<nsIClassInfo
*>(this);
178 NS_IMETHODIMP
nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo
**infop
)
184 NS_METHOD
nsGenericFactory::Create(nsISupports
* outer
, const nsIID
& aIID
, void* *aInstancePtr
)
186 // sorry, aggregation not spoken here.
187 nsresult res
= NS_ERROR_NO_AGGREGATION
;
189 nsGenericFactory
* factory
= new nsGenericFactory
;
190 if (factory
!= NULL
) {
191 res
= factory
->QueryInterface(aIID
, aInstancePtr
);
195 res
= NS_ERROR_OUT_OF_MEMORY
;
202 NS_NewGenericFactory(nsIGenericFactory
* *result
,
203 const nsModuleComponentInfo
*info
)
206 nsIGenericFactory
* fact
;
207 rv
= nsGenericFactory::Create(NULL
, NS_GET_IID(nsIGenericFactory
), (void**)&fact
);
208 if (NS_FAILED(rv
)) return rv
;
209 rv
= fact
->SetComponentInfo(info
);
210 if (NS_FAILED(rv
)) goto error
;
219 ////////////////////////////////////////////////////////////////////////////////
221 nsGenericModule::nsGenericModule(const char* moduleName
, PRUint32 componentCount
,
222 const nsModuleComponentInfo
* components
,
223 nsModuleConstructorProc ctor
,
224 nsModuleDestructorProc dtor
)
225 : mInitialized(PR_FALSE
),
226 mModuleName(moduleName
),
227 mComponentCount(componentCount
),
228 mComponents(components
),
229 mFactoriesNotToBeRegistered(nsnull
),
235 nsGenericModule::~nsGenericModule()
245 NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule
, nsIModule
)
248 nsGenericModule::AddFactoryNode(nsIGenericFactory
* fact
)
251 return NS_ERROR_FAILURE
;
253 FactoryNode
*node
= new FactoryNode(fact
, mFactoriesNotToBeRegistered
);
255 return NS_ERROR_OUT_OF_MEMORY
;
257 mFactoriesNotToBeRegistered
= node
;
262 // Perform our one-time intialization for this module
264 nsGenericModule::Initialize(nsIComponentManager
*compMgr
)
280 rv
= XPCOMGlueStartup(".");
285 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(compMgr
, &rv
);
289 // Eagerly populate factory/class object hash for entries
290 // without constructors. If we didn't, the class object would
291 // never get created. Also create the factory, which doubles
292 // as the class object, if the EAGER_CLASSINFO flag was given.
293 // This allows objects to be created (within their modules)
294 // via operator new rather than CreateInstance, yet still be
295 // QI'able to nsIClassInfo.
296 const nsModuleComponentInfo
* desc
= mComponents
;
297 for (PRUint32 i
= 0; i
< mComponentCount
; i
++) {
298 if (!desc
->mConstructor
||
299 (desc
->mFlags
& nsIClassInfo::EAGER_CLASSINFO
)) {
300 nsCOMPtr
<nsIGenericFactory
> fact
;
301 nsresult rv
= NS_NewGenericFactory(getter_AddRefs(fact
), desc
);
302 if (NS_FAILED(rv
)) return rv
;
304 // if we don't have a mConstructor, then we should not populate
305 // the component manager.
306 if (!desc
->mConstructor
) {
307 rv
= AddFactoryNode(fact
);
309 rv
= registrar
->RegisterFactory(desc
->mCID
,
314 if (NS_FAILED(rv
)) return rv
;
319 mInitialized
= PR_TRUE
;
323 // Shutdown this module, releasing all of the module resources
325 nsGenericModule::Shutdown()
327 // Free cached factories that were not registered.
329 while (mFactoriesNotToBeRegistered
)
331 node
= mFactoriesNotToBeRegistered
->mNext
;
332 delete mFactoriesNotToBeRegistered
;
333 mFactoriesNotToBeRegistered
= node
;
337 mInitialized
= PR_FALSE
;
344 // Create a factory object for creating instances of aClass.
346 nsGenericModule::GetClassObject(nsIComponentManager
*aCompMgr
,
353 // Defensive programming: Initialize *r_classObj in case of error below
355 return NS_ERROR_INVALID_POINTER
;
359 // Do one-time-only initialization if necessary
361 rv
= Initialize(aCompMgr
);
363 // Initialization failed! yikes!
368 // Choose the appropriate factory, based on the desired instance
369 // class type (aClass).
370 const nsModuleComponentInfo
* desc
= mComponents
;
371 for (PRUint32 i
= 0; i
< mComponentCount
; i
++) {
372 if (desc
->mCID
.Equals(aClass
)) {
373 nsCOMPtr
<nsIGenericFactory
> fact
;
374 rv
= NS_NewGenericFactory(getter_AddRefs(fact
), desc
);
375 if (NS_FAILED(rv
)) return rv
;
376 return fact
->QueryInterface(aIID
, r_classObj
);
380 // not found in descriptions
381 return NS_ERROR_FACTORY_NOT_REGISTERED
;
385 nsGenericModule::RegisterSelf(nsIComponentManager
*aCompMgr
,
387 const char* registryLocation
,
388 const char* componentType
)
393 printf_stderr("*** Registering components in: %s\n", mModuleName
);
396 const nsModuleComponentInfo
* cp
= mComponents
;
397 for (PRUint32 i
= 0; i
< mComponentCount
; i
++) {
398 // Register the component only if it has a constructor
399 if (cp
->mConstructor
) {
400 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(aCompMgr
, &rv
);
402 rv
= registrar
->RegisterFactoryLocation(cp
->mCID
,
410 printf_stderr("nsGenericModule %s: unable to register %s component => %x\n",
411 mModuleName
?mModuleName
:"(null)", cp
->mDescription
?cp
->mDescription
:"(null)", rv
);
416 // Call the registration hook of the component, if any
417 if (cp
->mRegisterSelfProc
)
419 rv
= cp
->mRegisterSelfProc(aCompMgr
, aPath
, registryLocation
,
423 printf_stderr("nsGenericModule %s: Register hook for %s component returned error => %x\n",
424 mModuleName
?mModuleName
:"(null)", cp
->mDescription
?cp
->mDescription
:"(null)", rv
);
436 nsGenericModule::UnregisterSelf(nsIComponentManager
* aCompMgr
,
438 const char* registryLocation
)
441 printf_stderr("*** Unregistering components in: %s\n", mModuleName
);
443 const nsModuleComponentInfo
* cp
= mComponents
;
444 for (PRUint32 i
= 0; i
< mComponentCount
; i
++) {
445 // Call the unregistration hook of the component, if any
446 if (cp
->mUnregisterSelfProc
)
448 cp
->mUnregisterSelfProc(aCompMgr
, aPath
, registryLocation
, cp
);
451 // Unregister the component
453 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(aCompMgr
, &rv
);
455 rv
= registrar
->UnregisterFactoryLocation(cp
->mCID
, aPath
);
458 printf_stderr("nsGenericModule %s: unable to unregister %s component => %x\n",
459 mModuleName
, cp
->mDescription
, rv
);
469 nsGenericModule::CanUnload(nsIComponentManager
*aCompMgr
, PRBool
*okToUnload
)
472 return NS_ERROR_INVALID_POINTER
;
474 *okToUnload
= PR_FALSE
;
475 return NS_ERROR_FAILURE
;
479 NS_NewGenericModule2(nsModuleInfo
const *info
, nsIModule
* *result
)
483 // Create and initialize the module instance
485 new nsGenericModule(info
->mModuleName
, info
->mCount
, info
->mComponents
,
486 info
->mCtor
, info
->mDtor
);
489 return NS_ERROR_OUT_OF_MEMORY
;
491 // Increase refcnt and store away nsIModule interface to m in result
492 NS_ADDREF(*result
= m
);
497 NS_NewGenericModule(const char* moduleName
,
498 PRUint32 componentCount
,
499 nsModuleComponentInfo
* components
,
500 nsModuleDestructorProc dtor
,
504 memset(&info
, 0, sizeof(info
));
506 info
.mVersion
= NS_MODULEINFO_VERSION
;
507 info
.mModuleName
= moduleName
;
508 info
.mComponents
= components
;
509 info
.mCount
= componentCount
;
512 return NS_NewGenericModule2(&info
, result
);
515 ////////////////////////////////////////////////////////////////////////////////