VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/glue/nsGenericFactory.cpp@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
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
4 *
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/
9 *
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
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
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.
21 *
22 * Contributor(s):
23 * Pierre Phaneuf <pp@ludusdesign.com>
24 *
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.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39
40// DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE()
41
42#include "nsGenericFactory.h"
43#include "nsMemory.h"
44#include "nsCOMPtr.h"
45#include "nsIComponentManager.h"
46#include "nsIComponentRegistrar.h"
47
48#ifdef XPCOM_GLUE
49#include "nsXPCOMGlue.h"
50#include "nsXPCOMPrivate.h"
51#else
52#include "nsIInterfaceRequestorUtils.h"
53#include "nsINativeComponentLoader.h"
54#endif
55
56nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
57 : mInfo(info)
58{
59 if (mInfo && mInfo->mClassInfoGlobal)
60 *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
61}
62
63nsGenericFactory::~nsGenericFactory()
64{
65 if (mInfo) {
66 if (mInfo->mFactoryDestructor)
67 mInfo->mFactoryDestructor();
68 if (mInfo->mClassInfoGlobal)
69 *mInfo->mClassInfoGlobal = 0;
70 }
71}
72
73NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory,
74 nsIGenericFactory,
75 nsIFactory,
76 nsIClassInfo)
77
78NS_IMETHODIMP nsGenericFactory::CreateInstance(nsISupports *aOuter,
79 REFNSIID aIID, void **aResult)
80{
81 if (mInfo->mConstructor) {
82 return mInfo->mConstructor(aOuter, aIID, aResult);
83 }
84
85 return NS_ERROR_FACTORY_NOT_REGISTERED;
86}
87
88NS_IMETHODIMP nsGenericFactory::LockFactory(PRBool aLock)
89{
90 // XXX do we care if (mInfo->mFlags & THREADSAFE)?
91 return NS_OK;
92}
93
94NS_IMETHODIMP nsGenericFactory::GetInterfaces(PRUint32 *countp,
95 nsIID* **array)
96{
97 if (!mInfo->mGetInterfacesProc) {
98 *countp = 0;
99 *array = nsnull;
100 return NS_OK;
101 }
102 return mInfo->mGetInterfacesProc(countp, array);
103}
104
105NS_IMETHODIMP nsGenericFactory::GetHelperForLanguage(PRUint32 language,
106 nsISupports **helper)
107{
108 if (mInfo->mGetLanguageHelperProc)
109 return mInfo->mGetLanguageHelperProc(language, helper);
110 *helper = nsnull;
111 return NS_OK;
112}
113
114NS_IMETHODIMP nsGenericFactory::GetContractID(char **aContractID)
115{
116 if (mInfo->mContractID) {
117 *aContractID = (char *)nsMemory::Alloc(strlen(mInfo->mContractID) + 1);
118 if (!*aContractID)
119 return NS_ERROR_OUT_OF_MEMORY;
120 strcpy(*aContractID, mInfo->mContractID);
121 } else {
122 *aContractID = nsnull;
123 }
124 return NS_OK;
125}
126
127NS_IMETHODIMP nsGenericFactory::GetClassDescription(char * *aClassDescription)
128{
129 if (mInfo->mDescription) {
130 *aClassDescription = (char *)
131 nsMemory::Alloc(strlen(mInfo->mDescription) + 1);
132 if (!*aClassDescription)
133 return NS_ERROR_OUT_OF_MEMORY;
134 strcpy(*aClassDescription, mInfo->mDescription);
135 } else {
136 *aClassDescription = nsnull;
137 }
138 return NS_OK;
139}
140
141NS_IMETHODIMP nsGenericFactory::GetClassID(nsCID * *aClassID)
142{
143 *aClassID =
144 NS_REINTERPRET_CAST(nsCID*,
145 nsMemory::Clone(&mInfo->mCID, sizeof mInfo->mCID));
146 if (! *aClassID)
147 return NS_ERROR_OUT_OF_MEMORY;
148 return NS_OK;
149}
150
151NS_IMETHODIMP nsGenericFactory::GetClassIDNoAlloc(nsCID *aClassID)
152{
153 *aClassID = mInfo->mCID;
154 return NS_OK;
155}
156
157NS_IMETHODIMP nsGenericFactory::GetImplementationLanguage(PRUint32 *langp)
158{
159 *langp = nsIProgrammingLanguage::CPLUSPLUS;
160 return NS_OK;
161}
162
163NS_IMETHODIMP nsGenericFactory::GetFlags(PRUint32 *flagsp)
164{
165 *flagsp = mInfo->mFlags;
166 return NS_OK;
167}
168
169// nsIGenericFactory: component-info accessors
170NS_IMETHODIMP nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo *info)
171{
172 if (mInfo && mInfo->mClassInfoGlobal)
173 *mInfo->mClassInfoGlobal = 0;
174 mInfo = info;
175 if (mInfo && mInfo->mClassInfoGlobal)
176 *mInfo->mClassInfoGlobal = NS_STATIC_CAST(nsIClassInfo *, this);
177 return NS_OK;
178}
179
180NS_IMETHODIMP nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo **infop)
181{
182 *infop = mInfo;
183 return NS_OK;
184}
185
186NS_METHOD nsGenericFactory::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
187{
188 // sorry, aggregation not spoken here.
189 nsresult res = NS_ERROR_NO_AGGREGATION;
190 if (outer == NULL) {
191 nsGenericFactory* factory = new nsGenericFactory;
192 if (factory != NULL) {
193 res = factory->QueryInterface(aIID, aInstancePtr);
194 if (res != NS_OK)
195 delete factory;
196 } else {
197 res = NS_ERROR_OUT_OF_MEMORY;
198 }
199 }
200 return res;
201}
202
203NS_COM nsresult
204NS_NewGenericFactory(nsIGenericFactory* *result,
205 const nsModuleComponentInfo *info)
206{
207 nsresult rv;
208 nsIGenericFactory* fact;
209 rv = nsGenericFactory::Create(NULL, NS_GET_IID(nsIGenericFactory), (void**)&fact);
210 if (NS_FAILED(rv)) return rv;
211 rv = fact->SetComponentInfo(info);
212 if (NS_FAILED(rv)) goto error;
213 *result = fact;
214 return rv;
215
216 error:
217 NS_RELEASE(fact);
218 return rv;
219}
220
221////////////////////////////////////////////////////////////////////////////////
222
223nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount,
224 const nsModuleComponentInfo* components,
225 nsModuleConstructorProc ctor,
226 nsModuleDestructorProc dtor,
227 const char** aLibDepends)
228 : mInitialized(PR_FALSE),
229 mModuleName(moduleName),
230 mComponentCount(componentCount),
231 mComponents(components),
232 mFactoriesNotToBeRegistered(nsnull),
233 mCtor(ctor),
234 mDtor(dtor),
235 mLibraryDependencies(aLibDepends)
236{
237}
238
239nsGenericModule::~nsGenericModule()
240{
241 Shutdown();
242
243#ifdef XPCOM_GLUE
244 XPCOMGlueShutdown();
245#endif
246
247}
248
249NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule, nsIModule)
250
251nsresult
252nsGenericModule::AddFactoryNode(nsIGenericFactory* fact)
253{
254 if (!fact)
255 return NS_ERROR_FAILURE;
256
257 FactoryNode *node = new FactoryNode(fact, mFactoriesNotToBeRegistered);
258 if (!node)
259 return NS_ERROR_OUT_OF_MEMORY;
260
261 mFactoriesNotToBeRegistered = node;
262 return NS_OK;
263}
264
265
266// Perform our one-time intialization for this module
267nsresult
268nsGenericModule::Initialize(nsIComponentManager *compMgr)
269{
270 nsresult rv;
271
272 if (mInitialized) {
273 return NS_OK;
274 }
275
276 if (mCtor) {
277 rv = mCtor(this);
278 if (NS_FAILED(rv))
279 return rv;
280 }
281
282
283#ifdef XPCOM_GLUE
284 rv = XPCOMGlueStartup(".");
285 if (NS_FAILED(rv))
286 return rv;
287#endif
288
289 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(compMgr, &rv);
290 if (NS_FAILED(rv))
291 return rv;
292
293 // Eagerly populate factory/class object hash for entries
294 // without constructors. If we didn't, the class object would
295 // never get created. Also create the factory, which doubles
296 // as the class object, if the EAGER_CLASSINFO flag was given.
297 // This allows objects to be created (within their modules)
298 // via operator new rather than CreateInstance, yet still be
299 // QI'able to nsIClassInfo.
300 const nsModuleComponentInfo* desc = mComponents;
301 for (PRUint32 i = 0; i < mComponentCount; i++) {
302 if (!desc->mConstructor ||
303 (desc->mFlags & nsIClassInfo::EAGER_CLASSINFO)) {
304 nsCOMPtr<nsIGenericFactory> fact;
305 nsresult rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
306 if (NS_FAILED(rv)) return rv;
307
308 // if we don't have a mConstructor, then we should not populate
309 // the component manager.
310 if (!desc->mConstructor) {
311 rv = AddFactoryNode(fact);
312 } else {
313 rv = registrar->RegisterFactory(desc->mCID,
314 desc->mDescription,
315 desc->mContractID,
316 fact);
317 }
318 if (NS_FAILED(rv)) return rv;
319 }
320 desc++;
321 }
322
323 mInitialized = PR_TRUE;
324 return NS_OK;
325}
326
327// Shutdown this module, releasing all of the module resources
328void
329nsGenericModule::Shutdown()
330{
331 // Free cached factories that were not registered.
332 FactoryNode* node;
333 while (mFactoriesNotToBeRegistered)
334 {
335 node = mFactoriesNotToBeRegistered->mNext;
336 delete mFactoriesNotToBeRegistered;
337 mFactoriesNotToBeRegistered = node;
338 }
339
340 if (mInitialized) {
341 mInitialized = PR_FALSE;
342
343 if (mDtor)
344 mDtor(this);
345 }
346}
347
348// Create a factory object for creating instances of aClass.
349NS_IMETHODIMP
350nsGenericModule::GetClassObject(nsIComponentManager *aCompMgr,
351 const nsCID& aClass,
352 const nsIID& aIID,
353 void** r_classObj)
354{
355 nsresult rv;
356
357 // Defensive programming: Initialize *r_classObj in case of error below
358 if (!r_classObj) {
359 return NS_ERROR_INVALID_POINTER;
360 }
361 *r_classObj = NULL;
362
363 // Do one-time-only initialization if necessary
364 if (!mInitialized) {
365 rv = Initialize(aCompMgr);
366 if (NS_FAILED(rv)) {
367 // Initialization failed! yikes!
368 return rv;
369 }
370 }
371
372 // Choose the appropriate factory, based on the desired instance
373 // class type (aClass).
374 const nsModuleComponentInfo* desc = mComponents;
375 for (PRUint32 i = 0; i < mComponentCount; i++) {
376 if (desc->mCID.Equals(aClass)) {
377 nsCOMPtr<nsIGenericFactory> fact;
378 rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
379 if (NS_FAILED(rv)) return rv;
380 return fact->QueryInterface(aIID, r_classObj);
381 }
382 desc++;
383 }
384 // not found in descriptions
385#ifndef XPCOM_GLUE
386#ifdef DEBUG
387 char* cs = aClass.ToString();
388 fprintf(stderr, "+++ nsGenericModule %s: unable to create factory for %s\n", mModuleName, cs);
389 // leak until we resolve the nsID Allocator.
390 // nsCRT::free(cs);
391#endif // XXX put in stop-gap so that we don't search for this one again
392#endif
393 return NS_ERROR_FACTORY_NOT_REGISTERED;
394}
395
396NS_IMETHODIMP
397nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr,
398 nsIFile* aPath,
399 const char* registryLocation,
400 const char* componentType)
401{
402 nsresult rv = NS_OK;
403
404#ifdef DEBUG
405 fprintf(stderr, "*** Registering %s components (all right -- a generic module!)\n", mModuleName);
406#endif
407
408 const nsModuleComponentInfo* cp = mComponents;
409 for (PRUint32 i = 0; i < mComponentCount; i++) {
410 // Register the component only if it has a constructor
411 if (cp->mConstructor) {
412 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
413 if (registrar)
414 rv = registrar->RegisterFactoryLocation(cp->mCID,
415 cp->mDescription,
416 cp->mContractID,
417 aPath,
418 registryLocation,
419 componentType);
420 if (NS_FAILED(rv)) {
421#ifdef DEBUG
422 fprintf(stderr, "nsGenericModule %s: unable to register %s component => %x\n",
423 mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
424#endif
425 break;
426 }
427 }
428 // Call the registration hook of the component, if any
429 if (cp->mRegisterSelfProc)
430 {
431 rv = cp->mRegisterSelfProc(aCompMgr, aPath, registryLocation,
432 componentType, cp);
433 if (NS_FAILED(rv)) {
434#ifdef DEBUG
435 fprintf(stderr, "nsGenericModule %s: Register hook for %s component returned error => %x\n",
436 mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
437#endif
438 break;
439 }
440 }
441 cp++;
442 }
443
444#ifndef XPCOM_GLUE
445 // We want to tell the component loader of any dependencies
446 // we have so that the loader can resolve them for us.
447
448 nsCOMPtr<nsINativeComponentLoader> loader = do_GetInterface(aCompMgr);
449 if (loader && mLibraryDependencies)
450 {
451 for(int i=0; mLibraryDependencies[i] != nsnull &&
452 mLibraryDependencies[i][0] != '\0'; i++)
453 {
454 loader->AddDependentLibrary(aPath,
455 mLibraryDependencies[i]);
456 }
457 loader = nsnull;
458 }
459#endif
460
461
462
463 return rv;
464}
465
466NS_IMETHODIMP
467nsGenericModule::UnregisterSelf(nsIComponentManager* aCompMgr,
468 nsIFile* aPath,
469 const char* registryLocation)
470{
471#ifdef DEBUG
472 fprintf(stderr, "*** Unregistering %s components (all right -- a generic module!)\n", mModuleName);
473#endif
474 const nsModuleComponentInfo* cp = mComponents;
475 for (PRUint32 i = 0; i < mComponentCount; i++) {
476 // Call the unregistration hook of the component, if any
477 if (cp->mUnregisterSelfProc)
478 {
479 cp->mUnregisterSelfProc(aCompMgr, aPath, registryLocation, cp);
480 }
481
482 // Unregister the component
483 nsresult rv;
484 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
485 if (registrar)
486 rv = registrar->UnregisterFactoryLocation(cp->mCID, aPath);
487 if (NS_FAILED(rv)) {
488#ifdef DEBUG
489 fprintf(stderr, "nsGenericModule %s: unable to unregister %s component => %x\n",
490 mModuleName, cp->mDescription, rv);
491#endif
492 }
493 cp++;
494 }
495
496 return NS_OK;
497}
498
499NS_IMETHODIMP
500nsGenericModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
501{
502 if (!okToUnload) {
503 return NS_ERROR_INVALID_POINTER;
504 }
505 *okToUnload = PR_FALSE;
506 return NS_ERROR_FAILURE;
507}
508
509NS_COM nsresult
510NS_NewGenericModule2(nsModuleInfo* info, nsIModule* *result)
511{
512 nsresult rv = NS_OK;
513
514 // Create and initialize the module instance
515 nsGenericModule *m =
516 new nsGenericModule(info->mModuleName, info->mCount, info->mComponents,
517 info->mCtor, info->mDtor, info->mLibraryDependencies);
518
519 if (!m)
520 return NS_ERROR_OUT_OF_MEMORY;
521
522 // Increase refcnt and store away nsIModule interface to m in result
523 NS_ADDREF(*result = m);
524 return rv;
525}
526
527NS_COM nsresult
528NS_NewGenericModule(const char* moduleName,
529 PRUint32 componentCount,
530 nsModuleComponentInfo* components,
531 nsModuleDestructorProc dtor,
532 nsIModule* *result)
533{
534 nsModuleInfo info;
535 memset(&info, 0, sizeof(info));
536
537 info.mVersion = NS_MODULEINFO_VERSION;
538 info.mModuleName = moduleName;
539 info.mComponents = components;
540 info.mCount = componentCount;
541 info.mDtor = dtor;
542 info.mLibraryDependencies = nsnull;
543
544 return NS_NewGenericModule2(&info, result);
545}
546
547////////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use