/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Sun Microsystems, * Inc. Portions created by Sun are * Copyright (C) 1999 Sun Microsystems, Inc. All * Rights Reserved. * * Contributor(s): * Sergey Lunegov */ /* A bunch of stuff was copied from mozJSComponentLoader.cpp */ #include #include "nsICategoryManager.h" #include "urpComponentLoader.h" #include "urpComponentFactory.h" #include "nsCOMPtr.h" #include "nsIModule.h" #include "nsIGenericFactory.h" #include "nsXPIDLString.h" #include "nsCRT.h" #include "../urpLog.h" const char urpComponentTypeName[] = URPCOMPONENTTYPENAME; /* XXX export properly from libxpcom, for now this will let Mac build */ #ifdef RHAPSODY extern const char fileSizeValueName[]; // = "FileSize"; extern const char lastModValueName[]; // = "LastModTimeStamp"; extern const char xpcomKeyName[]; // = "Software/Mozilla/XPCOM"; #else const char fileSizeValueName[] = "FileSize"; const char lastModValueName[] = "LastModTimeStamp"; const char xpcomKeyName[] = "software/mozilla/XPCOM/components"; #endif NS_IMPL_THREADSAFE_ISUPPORTS(urpComponentLoader,NS_GET_IID(nsIComponentLoader)); urpComponentLoader::urpComponentLoader() : mCompMgr(NULL), mXPCOMKey(0) { NS_INIT_REFCNT(); PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::urpComponentLoader \n")); } urpComponentLoader::~urpComponentLoader() { //nb PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::~urpComponentLoader \n")); } /** * Get the factory for a given component. */ /* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */ NS_IMETHODIMP urpComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval) { PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::GetFactory \n")); if (!_retval) return NS_ERROR_NULL_POINTER; #ifdef DEBUG char *cidString = aCID.ToString(); fprintf(stderr, "--urpComponentLoader::GetFactory(%s,%s,%s)\n", cidString, aLocation, aType); delete [] cidString; #endif // nsIFactory *f = new urpComponentFactory(aLocation, aCID, proxy); nsIFactory *f = new urpComponentFactory(aLocation, aCID); NS_ADDREF(f); *_retval = f; return NS_OK; } /** * Initialize the loader. * * We use nsISupports here because nsIRegistry isn't IDLized yet. */ /* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */ NS_IMETHODIMP urpComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg) { PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::Init \n")); nsresult rv; mCompMgr = aCompMgr; mRegistry = do_QueryInterface(aReg, &rv); if (NS_SUCCEEDED(rv)) { rv = mRegistry->GetSubtree(nsIRegistry::Common, xpcomKeyName, &mXPCOMKey); if (NS_FAILED(rv)) /* if we can't get the XPCOM key, just skip all registry ops */ mRegistry = nsnull; } return NS_OK; } /** * Called when a component of the appropriate type is registered, * to give the component loader an opportunity to do things like * annotate the registry and such. */ /* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */ NS_IMETHODIMP urpComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist) { //nb PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::OnRegister \n")); return NS_OK; } /** * AutoRegister components in the given directory. */ NS_IMETHODIMP urpComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory) { PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::AutoRegisterComponents \n")); return RegisterComponentsInDir(aWhen,aDirectory); } NS_IMETHODIMP urpComponentLoader::AutoUnregisterComponent(PRInt32 when, nsIFile *component, PRBool *unregistered) { //nb need to impelement return NS_OK; } nsresult urpComponentLoader::RegisterComponentsInDir(PRInt32 when, nsIFile *dir) { nsresult rv; PRBool isDir; if (NS_FAILED(rv = dir->IsDirectory(&isDir))) return rv; if (!isDir) return NS_ERROR_INVALID_ARG; // Create a directory iterator nsCOMPtr dirIterator; rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator)); if (NS_FAILED(rv)) return rv; // whip through the directory to register every file nsIFile *dirEntry = NULL; PRBool more = PR_FALSE; rv = dirIterator->HasMoreElements(&more); if (NS_FAILED(rv)) return rv; while (more == PR_TRUE) { rv = dirIterator->GetNext((nsISupports**)&dirEntry); if (NS_SUCCEEDED(rv)) { rv = dirEntry->IsDirectory(&isDir); if (NS_SUCCEEDED(rv)) { if (isDir == PR_TRUE) { // This is a directory. Grovel for components into the directory. rv = RegisterComponentsInDir(when, dirEntry); } else { PRBool registered; // This is a file. Try to register it. rv = AutoRegisterComponent(when, dirEntry, ®istered); } } NS_RELEASE(dirEntry); } rv = dirIterator->HasMoreElements(&more); if (NS_FAILED(rv)) return rv; } return NS_OK; } /** * AutoRegister the given component. * * Returns true if the component was registered, false if it couldn't * attempt to register the component (wrong type) and ``throws'' an * NS_FAILED code if there was an error during registration. */ /* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */ /* copied from mozJSComponentLoader.cpp */ NS_IMETHODIMP urpComponentLoader::AutoRegisterComponent(PRInt32 when, nsIFile *component, PRBool *registered) { //printf("--urpComponentLoader::AutoRegisterComponent \n"); nsresult rv; if (!registered) return NS_ERROR_NULL_POINTER; const char javaExtension[] = ".urp.info"; int javaExtensionLen = 9; nsXPIDLCString leafName; *registered = PR_FALSE; /* we only do files */ PRBool isFile = PR_FALSE; if (NS_FAILED(rv = component->IsFile(&isFile)) || !isFile) return rv; if (NS_FAILED(rv = component->GetLeafName(getter_Copies(leafName)))) return rv; int len = PL_strlen(leafName); /* if it's not javaExtension return now */ if (len < javaExtensionLen || // too short PL_strcasecmp(leafName + len - javaExtensionLen, javaExtension)) return NS_OK; PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader: registering urpComponent component %s\n",(const char *)leafName)); rv = AttemptRegistration(component, PR_FALSE); if (NS_SUCCEEDED(rv)) PR_LOG(log, PR_LOG_DEBUG, ("registered module %s\n", (const char *)leafName)); else if (rv == NS_ERROR_FACTORY_REGISTER_AGAIN) PR_LOG(log, PR_LOG_DEBUG, ("deferred module %s\n", (const char *)leafName)); else PR_LOG(log, PR_LOG_DEBUG, ("failed to register %s\n", (const char *)leafName)); *registered = (PRBool) NS_SUCCEEDED(rv); return NS_OK; } nsresult urpComponentLoader::AttemptRegistration(nsIFile *component, PRBool deferred) { nsXPIDLCString registryLocation; nsresult rv; nsIModule *module; rv = mCompMgr->RegistryLocationForSpec(component, getter_Copies(registryLocation)); nsXPIDLCString str; component->GetPath(getter_Copies(str)); const char* location = nsCRT::strdup(str); ifstream in(location); char cidStr[500], contractid[1000], desc[1000]; in.getline(cidStr,1000); in.getline(contractid,1000); in.getline(desc,1000); PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("%s %s %s", cidStr, contractid, desc)); nsCID cid; cid.Parse((const char *)cidStr); mCompMgr->RegisterComponentWithType(cid, desc, contractid, component, registryLocation, PR_TRUE, PR_TRUE, urpComponentTypeName); if (NS_FAILED(rv)) return rv; /* no need to check registry data on deferred reg */ SetRegistryInfo(registryLocation, component); return rv; } nsresult urpComponentLoader::SetRegistryInfo(const char *registryLocation, nsIFile *component) { if (!mRegistry.get()) return NS_OK; // silent failure nsresult rv; nsRegistryKey key; rv = mRegistry->AddSubtreeRaw(mXPCOMKey, registryLocation, &key); if (NS_FAILED(rv)) return rv; PRInt64 modDate; if (NS_FAILED(rv = component->GetLastModifiedTime(&modDate)) || NS_FAILED(rv = mRegistry->SetLongLong(key, lastModValueName, &modDate))) return rv; PRInt64 fileSize; if (NS_FAILED(rv = component->GetFileSize(&fileSize)) || NS_FAILED(rv = mRegistry->SetLongLong(key, fileSizeValueName, &fileSize))) return rv; PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("SetRegistryInfo(%s) => (%d,%d)\n", registryLocation, (int)modDate, (int)fileSize)); return NS_OK; } PRBool urpComponentLoader::HasChanged(const char *registryLocation, nsIFile *component) { /* if we don't have a registry handle, force registration of component */ if (!mRegistry) return PR_TRUE; nsRegistryKey key; if (NS_FAILED(mRegistry->GetSubtreeRaw(mXPCOMKey, registryLocation, &key))) return PR_TRUE; /* check modification date */ PRInt64 regTime, lastTime; if (NS_FAILED(mRegistry->GetLongLong(key, lastModValueName, ®Time))) return PR_TRUE; if (NS_FAILED(component->GetLastModifiedTime(&lastTime)) || LL_NE(lastTime, regTime)) return PR_TRUE; /* check file size */ PRInt64 regSize; if (NS_FAILED(mRegistry->GetLongLong(key, fileSizeValueName, ®Size))) return PR_TRUE; PRInt64 size; if (NS_FAILED(component->GetFileSize(&size)) || LL_NE(size,regSize) ) return PR_TRUE; return PR_FALSE; } /** * Register any deferred (NS_ERROR_FACTORY_REGISTER_AGAIN) components. * Return registered-any-components? */ /* boolean registerDeferredComponents (in long aWhen); */ NS_IMETHODIMP urpComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *aRegistered) { PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::RegisterDeferredComponents \n")); nsresult rv; *aRegistered = PR_FALSE; PRUint32 count; rv = mDeferredComponents.Count(&count); printf("mJCL: registering deferred (%d)\n", count); if (NS_FAILED(rv) || !count) return NS_OK; for (PRUint32 i = 0; i < count; i++) { nsCOMPtr supports; nsCOMPtr component; rv = mDeferredComponents.GetElementAt(i, getter_AddRefs(supports)); if (NS_FAILED(rv)) continue; component = do_QueryInterface(supports, &rv); if (NS_FAILED(rv)) continue; rv = AttemptRegistration(component, PR_TRUE /* deferred */); if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) { if (NS_SUCCEEDED(rv)) *aRegistered = PR_TRUE; mDeferredComponents.RemoveElementAt(i); } } rv = mDeferredComponents.Count(&count); if (NS_SUCCEEDED(rv)) { if (*aRegistered) printf("mJCL: registered deferred, %d left\n", count); else printf("mJCL: didn't register any components, %d left\n", count); } /* are there any fatal errors? */ return NS_OK; } /** * Unload all components that are willing. */ /* void unloadAll (in long aWhen); */ NS_IMETHODIMP urpComponentLoader::UnloadAll(PRInt32 aWhen) { //nb PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("--urpComponentLoader::UnloadAll \n")); return NS_OK; } //--------------------------------------------------------------------------------------------------- /* XXX this should all be data-driven, via NS_IMPL_GETMODULE_WITH_CATEGORIES */ static NS_METHOD RegisterRemoteLoader(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *registryLocation, const char *componentType, const nsModuleComponentInfo *info) { PRLogModuleInfo *log = urpLog::GetLog(); nsresult rv; nsCOMPtr catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); PR_LOG(log, PR_LOG_DEBUG, ("--URPLoader got registered\n")); if (NS_FAILED(rv)) return rv; nsXPIDLCString previous; rv = catman->AddCategoryEntry("component-loader", urpComponentTypeName, URP_COMPONENTLOADER_ContractID, PR_TRUE, PR_TRUE, getter_Copies(previous)); if(NS_FAILED(rv)) PR_LOG(log, PR_LOG_DEBUG, ("Adding of remote-comp-loader is failed\n")); else PR_LOG(log, PR_LOG_DEBUG, ("Adding of remote-comp-loader is succeseded\n")); nsXPIDLCString urpLoader; rv = catman->GetCategoryEntry("component-loader", urpComponentTypeName, getter_Copies(urpLoader)); if (NS_FAILED(rv)) PR_LOG(log, PR_LOG_DEBUG, ("didn't got category entry\n")); else PR_LOG(log, PR_LOG_DEBUG, ("got category entry\n")); return rv; } static NS_METHOD UnregisterRemoteLoader(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *registryLocation, const nsModuleComponentInfo *info) { nsresult rv; nsCOMPtr catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; nsXPIDLCString urpLoader; PRLogModuleInfo *log = urpLog::GetLog(); PR_LOG(log, PR_LOG_DEBUG, ("URP component loader is being unregistered\n")); rv = catman->GetCategoryEntry("component-loader", urpComponentTypeName, getter_Copies(urpLoader)); if (NS_FAILED(rv)) return rv; // only unregister if we're the current JS component loader if (!strcmp(urpLoader, URP_COMPONENTLOADER_ContractID)) { return catman->DeleteCategoryEntry("component-loader", urpComponentTypeName, PR_TRUE, getter_Copies(urpLoader)); } return NS_OK; } NS_GENERIC_FACTORY_CONSTRUCTOR(urpComponentLoader); static nsModuleComponentInfo components[] = { { "URP component loader", URP_COMPONENTLOADER_CID, URP_COMPONENTLOADER_ContractID, urpComponentLoaderConstructor, RegisterRemoteLoader, UnregisterRemoteLoader } }; NS_IMPL_NSGETMODULE("URP component loader", components);