#include #include #include #include #include #include #include #include #include using namespace ::com::sun::star::bridge; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::loader; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::registry; using namespace ::cppu; using namespace ::rtl; namespace dynamic_loader { class SingleServiceFactory : public WeakImplHelper2 { Reference _xServiceManager; OUString _serviceName; OUString _link; OUString _resolver; Reference getRemoteFactory() throw(Exception, RuntimeException); public: SingleServiceFactory(const Reference & xServiceManager, const OUString & serviceName, const OUString & link, const OUString & resolver) : _xServiceManager(xServiceManager), _serviceName(serviceName), _link(link), _resolver(resolver) {} // XSingleServiceFactory Reference SAL_CALL createInstance() throw(Exception, RuntimeException); Reference SAL_CALL createInstanceWithArguments(const Sequence& Arguments) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); // XServiceInfo OUString SAL_CALL getImplementationName() throw(RuntimeException); sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException); Sequence SAL_CALL getSupportedServiceNames(void) throw(RuntimeException); }; Reference SingleServiceFactory::getRemoteFactory() throw(Exception, RuntimeException) { Reference xResolver(_xServiceManager->createInstance(_resolver), UNO_QUERY); if(!xResolver.is()) { OUString message(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::singleServiceFactory.createInstance - couldn't create resolver: ")); message += _resolver; throw Exception(message, Reference()); } Reference remoteObject = xResolver->resolve(_link); if(!remoteObject.is()) { OUString message(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::singleServiceFactory.createInstance - couldn't resolve link: ")); message += _link; throw Exception(message, Reference()); } Reference remoteFactory(remoteObject, UNO_QUERY); if(!remoteFactory.is()) { OUString message(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::singleServiceFactory.createInstance - couldn't get XSingleServiceFactory from: ")); message += _link; throw Exception(message, Reference()); } return remoteFactory; } // XSingleServiceFactory Reference SAL_CALL SingleServiceFactory::createInstance() throw(Exception, RuntimeException) { OSL_TRACE("dynamic_loader::singleServiceFactory::createInstance"); return getRemoteFactory()->createInstance(); } Reference SAL_CALL SingleServiceFactory::createInstanceWithArguments(const Sequence& Arguments) throw(Exception, RuntimeException) { OSL_TRACE("dynamic_loader::singleServiceFactory::createInstanceWithArguments"); return getRemoteFactory()->createInstanceWithArguments(Arguments); } // XServiceInfo OUString SAL_CALL SingleServiceFactory::getImplementationName() throw(RuntimeException) { return _link; } sal_Bool SAL_CALL SingleServiceFactory::supportsService(const OUString & ServiceName) throw(RuntimeException) { return _serviceName.equals(ServiceName); } Sequence SAL_CALL SingleServiceFactory::getSupportedServiceNames(void) throw(RuntimeException) { return Sequence(&_serviceName, 1); } class DynamicLoader : public WeakImplHelper2 { Reference _xSMgr; protected: DynamicLoader(const Reference & rXSMgr) throw(RuntimeException); ~DynamicLoader() throw(); public: static const OUString implname; static const OUString servname; static Reference SAL_CALL createInstance(const Reference & rSMgr) throw(Exception); static Sequence SAL_CALL getSupportedServiceNames_Static() throw(); static void parseUrl(const OUString & url, OUString * serviceName, OUString * link, OUString * resolver) throw(RuntimeException); // XServiceInfo virtual OUString SAL_CALL getImplementationName() throw(RuntimeException); virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException); virtual Sequence SAL_CALL getSupportedServiceNames() throw(RuntimeException); // XImplementationLoader virtual Reference SAL_CALL activate(const OUString & implementationName, const OUString & implementationLoaderUrl, const OUString& locationUrl, const Reference& xKey) throw(CannotActivateFactoryException, RuntimeException); virtual sal_Bool SAL_CALL writeRegistryInfo(const Reference& xKey, const OUString& implementationLoaderUrl, const OUString& locationUrl) throw(CannotRegisterImplementationException, RuntimeException); }; const OUString DynamicLoader::implname = OUString::createFromAscii("com.sun.star.comp.stoc.DynamicLoader"); const OUString DynamicLoader::servname = OUString::createFromAscii("com.sun.star.loader.Dynamic"); Sequence SAL_CALL DynamicLoader::getSupportedServiceNames_Static() throw() { return Sequence(&servname, 1); } Reference SAL_CALL DynamicLoader::createInstance(const Reference & rSMgr) throw(Exception) { Reference xRet; try { XImplementationLoader *pXLoader = (XImplementationLoader *)new DynamicLoader(rSMgr); xRet = Reference::query(pXLoader); } catch(RuntimeException & runtimeException) { OString message = OUStringToOString(runtimeException.Message, RTL_TEXTENCODING_ASCII_US); osl_trace("dynamic loader - could not init cause of %s", message.getStr()); } OSL_TRACE("DynamicLoader - createInstance: %d", xRet.is()); return xRet; } DynamicLoader::DynamicLoader(const Reference & xSMgr) throw(RuntimeException) : _xSMgr(xSMgr) { } DynamicLoader::~DynamicLoader() throw() { } // XServiceInfo OUString SAL_CALL DynamicLoader::getImplementationName() throw(RuntimeException) { return implname; } sal_Bool SAL_CALL DynamicLoader::supportsService(const OUString & ServiceName) throw(RuntimeException) { sal_Bool bSupport = sal_False; Sequence aSNL = getSupportedServiceNames(); const OUString * pArray = aSNL.getArray(); for(sal_Int32 i = 0; i < aSNL.getLength() && !bSupport; ++ i) bSupport = pArray[i] == ServiceName; return bSupport; } Sequence SAL_CALL DynamicLoader::getSupportedServiceNames() throw(RuntimeException) { return getSupportedServiceNames_Static(); } void DynamicLoader::parseUrl(const OUString & locationUrl, OUString * serviceName, OUString * link, OUString * resolver) throw(RuntimeException) { #if OSL_DEBUG_LEVEL > 1 OString tmp = OUStringToOString(locationUrl, RTL_TEXTENCODING_ASCII_US); OSL_TRACE("DynamicLoader - locationUrl %s", tmp.getStr()); #endif // This is the default resolver *resolver = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.UnoUrlResolver")); const OUString bSlash(OUString(RTL_CONSTASCII_USTRINGPARAM("\\"))); const OUString tuedle(OUString(RTL_CONSTASCII_USTRINGPARAM("\""))); const OUString separator(OUString(RTL_CONSTASCII_USTRINGPARAM(","))); const OUString emptyString(OUString(RTL_CONSTASCII_USTRINGPARAM(""))); const OUString equalSign(OUString(RTL_CONSTASCII_USTRINGPARAM("="))); sal_Int32 index = 0; sal_Bool left = sal_True; sal_Bool quote = sal_False; sal_Bool inString = sal_False; const sal_Unicode * raw_url = locationUrl.getStr(); OUString token; OUString attribute; while(index <= locationUrl.getLength()) { if(index >= locationUrl.getLength() || (raw_url[index] == separator.getStr()[0] && !quote && !inString)) { // a separator or end? OUString value; if(left) attribute = token.trim(); else value = token.trim(); #if OSL_DEBUG_LEVEL > 1 OString attribute_tmp = OUStringToOString(attribute, RTL_TEXTENCODING_ASCII_US); OSL_TRACE("DynamicLoader - attribute %s", attribute_tmp.getStr()); OString value_tmp = OUStringToOString(value, RTL_TEXTENCODING_ASCII_US); OSL_TRACE("DynamicLoader - value %s", value_tmp.getStr()); #endif if(attribute.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("servicename")))) *serviceName = value; else if(attribute.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("link")))) *link = value; else if(attribute.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("resolver")))) *resolver = value; else { OUString message(RTL_CONSTASCII_USTRINGPARAM("help called")); if(!attribute.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("help")))) { message = OUString(RTL_CONSTASCII_USTRINGPARAM("DynamicLoader - unknown attribute: ")); message += attribute; } fprintf(stdout, "DynamicLoader - help\n"); fprintf(stdout, "attributes:\n"); fprintf(stdout, "\tservicename: service name of dynamic component\n"); fprintf(stdout, "\tlink: link to a single service factory for dynamic component\n"); fprintf(stdout, "\tresolver: the service which resolves the link\n"); fprintf(stdout, "\thelp: this help\n"); throw RuntimeException(message, Reference()); } left = sal_True; // reset state to be left token = emptyString; } else if(raw_url[index] == bSlash.getStr()[0] && !quote) // a back slash? quote = sal_True; else if(raw_url[index] == equalSign.getStr()[0] && !quote && !inString) { // equalSign (switch from left to right)? left = sal_False; attribute = token.trim(); token = emptyString; } else if(raw_url[index] == tuedle.getStr()[0] && !quote) // begin or end of string? inString = !inString; else { // no special handling token += OUString(raw_url + index, 1); quote = sal_False; } ++ index; } // enshure, that attributes are set properly if(!(*serviceName).getLength()) throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::DynamicLoader.parseUrl - missing or empty attribute: servicename")), Reference()); if(!(*link).getLength()) throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::DynamicLoader.parseUrl - missing or empty attribute: link")), Reference()); if(!(*resolver).getLength()) throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("dynamic_loader::DynamicLoader.parseUrl - missing or empty attribute: resolver")), Reference()); } // XImplementationLoader sal_Bool SAL_CALL DynamicLoader::writeRegistryInfo(const Reference & xKey, const OUString & implementationLoaderUrl, const OUString & locationUrl) throw(CannotRegisterImplementationException, RuntimeException) { OSL_TRACE("DynamicLoader::writeRegistryInfo"); OUString serviceName; OUString link; OUString resolver; try { parseUrl(locationUrl, &serviceName, &link, &resolver); } catch(RuntimeException & runtimeException) { throw CannotRegisterImplementationException(runtimeException.Message, Reference()); } // create the keys OUString keyName = OUString::createFromAscii("/"); keyName += implementationLoaderUrl; keyName += OUString(RTL_CONSTASCII_USTRINGPARAM("_")); keyName += serviceName; keyName += OUString::createFromAscii("/UNO/SERVICES"); Reference xNewKey(xKey->createKey(keyName)); xNewKey->createKey(serviceName); sal_Bool bSuccess = sal_True; return bSuccess; } Reference SAL_CALL DynamicLoader::activate(const OUString & rImplName, const OUString & loaderUrl, const OUString & locationUrl, const Reference & xKey) throw(CannotActivateFactoryException, RuntimeException) { OSL_TRACE("DynamicLoader::activate"); OUString serviceName; OUString link; OUString resolver; parseUrl(locationUrl, &serviceName, &link, &resolver); XSingleServiceFactory * xFactory = (XSingleServiceFactory *)new SingleServiceFactory(_xSMgr, serviceName, link, resolver); Reference xReturn; if(xFactory) xReturn = Reference::query(xFactory); return xReturn; } } extern "C" { void SAL_CALL component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } sal_Bool SAL_CALL component_writeInfo(XMultiServiceFactory * pServiceManager, XRegistryKey * pRegistryKey) { sal_Bool bRes = sal_False; if (pRegistryKey) { try { OUString x = OUString::createFromAscii("/"); x += ::dynamic_loader::DynamicLoader::implname; x += OUString::createFromAscii("/UNO/SERVICES"); Reference xNewKey(pRegistryKey->createKey(x)); const Sequence rSNL = ::dynamic_loader::DynamicLoader::getSupportedServiceNames_Static(); const OUString * pArray = rSNL.getConstArray(); for (sal_Int32 nPos = rSNL.getLength(); nPos--;) xNewKey->createKey(pArray[nPos]); bRes = sal_True; } catch (InvalidRegistryException &) { OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); } } return bRes; } void * SAL_CALL component_getFactory(const sal_Char * pImplName, XMultiServiceFactory * pServiceManager, XRegistryKey * pRegistryKey) { void * pRet = 0; if (pServiceManager && OUString::createFromAscii(pImplName).equals(::dynamic_loader::DynamicLoader::implname)) { Reference xFactory(createOneInstanceFactory(pServiceManager, ::dynamic_loader::DynamicLoader::implname, ::dynamic_loader::DynamicLoader::createInstance, ::dynamic_loader::DynamicLoader::getSupportedServiceNames_Static())); if (xFactory.is()) { xFactory->acquire(); pRet = xFactory.get(); } } else OSL_TRACE("DynamicLoader - warning - given wrong implName: %s", pImplName); return pRet; } }